Implement backend access with SSO
This commit is contained in:
Vendored
+1
-1
Submodule 3rdparty/QtZeroConf updated: 2fbb52b708...8f72314407
Vendored
+1
-1
Submodule 3rdparty/qmsgpack updated: cd3fcec745...05aa4b2e0d
@@ -1203,7 +1203,7 @@
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>DevicesConnection</name>
|
||||
<name>DeviceConnection</name>
|
||||
<message>
|
||||
<location filename="../../flotten-updater/deviceconnection.cpp" line="79"/>
|
||||
<location filename="../../flotten-updater/deviceconnection.cpp" line="311"/>
|
||||
|
||||
@@ -160,6 +160,11 @@ NavigationPage {
|
||||
text: qsTr("Skip server cert verification")
|
||||
}
|
||||
|
||||
GeneralOnOffSwitch {
|
||||
apiKey: "ocppt"
|
||||
text: qsTr("Accept time from backend")
|
||||
}
|
||||
|
||||
// TODO clientKey
|
||||
|
||||
// TODO clientCert
|
||||
|
||||
@@ -12,9 +12,9 @@ qt_add_executable(flotten-updater WIN32 MACOSX_BUNDLE
|
||||
devicesmodel.h
|
||||
flottenupdatersettings.cpp
|
||||
flottenupdatersettings.h
|
||||
importcertificatedialog.cpp
|
||||
importcertificatedialog.h
|
||||
importcertificatedialog.ui
|
||||
importcredentialsdialog.cpp
|
||||
importcredentialsdialog.h
|
||||
importcredentialsdialog.ui
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
|
||||
@@ -24,42 +24,44 @@ const constexpr QColor blue{150, 150, 255};
|
||||
const constexpr QColor magenta{255, 150, 255};
|
||||
}
|
||||
|
||||
DevicesConnection::DevicesConnection(const QSslKey &key, const QSslCertificate &cert, QString &&serial, QObject *parent) :
|
||||
DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent) :
|
||||
QObject{parent},
|
||||
m_serial(std::move(serial)),
|
||||
m_key{key},
|
||||
m_cert{cert}
|
||||
m_username{username},
|
||||
m_password{password}
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
DevicesConnection::DevicesConnection(const QSslKey &key, const QSslCertificate &cert, const QString &serial, QObject *parent) :
|
||||
DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent) :
|
||||
QObject{parent},
|
||||
m_serial(serial),
|
||||
m_key{key},
|
||||
m_cert{cert}
|
||||
m_username{username},
|
||||
m_password{password}
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void DevicesConnection::start()
|
||||
void DeviceConnection::start()
|
||||
{
|
||||
const QUrl url{QString("wss://solalaweb.com/%0").arg(m_serial)};
|
||||
qDebug() << url;
|
||||
m_websocket.open(url);
|
||||
QNetworkRequest request{QString("wss://solalaweb.com/%0").arg(m_serial)};
|
||||
QString credentials = m_username + ':' + m_password;
|
||||
QString base64 = credentials.toUtf8().toBase64();
|
||||
request.setRawHeader("Authorization", "Basic " + base64.toUtf8());
|
||||
m_websocket.open(request);
|
||||
}
|
||||
|
||||
void DevicesConnection::stop()
|
||||
void DeviceConnection::stop()
|
||||
{
|
||||
m_websocket.close();
|
||||
}
|
||||
|
||||
QString DevicesConnection::wsStatusText() const
|
||||
QString DeviceConnection::wsStatusText() const
|
||||
{
|
||||
return QMetaEnum::fromType<QAbstractSocket::SocketState>().valueToKey(m_websocket.state());
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::wsStatusBackground() const
|
||||
QBrush DeviceConnection::wsStatusBackground() const
|
||||
{
|
||||
switch (m_websocket.state())
|
||||
{
|
||||
@@ -72,7 +74,7 @@ QBrush DevicesConnection::wsStatusBackground() const
|
||||
return {};
|
||||
}
|
||||
|
||||
QString DevicesConnection::statusText() const
|
||||
QString DeviceConnection::statusText() const
|
||||
{
|
||||
switch (m_status)
|
||||
{
|
||||
@@ -84,7 +86,7 @@ QString DevicesConnection::statusText() const
|
||||
return QString::number(std::to_underlying(m_status));
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::statusBackground() const
|
||||
QBrush DeviceConnection::statusBackground() const
|
||||
{
|
||||
switch (m_status)
|
||||
{
|
||||
@@ -95,7 +97,7 @@ QBrush DevicesConnection::statusBackground() const
|
||||
return {};
|
||||
}
|
||||
|
||||
QString DevicesConnection::variantText() const
|
||||
QString DeviceConnection::variantText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("var"))
|
||||
return {};
|
||||
@@ -103,7 +105,7 @@ QString DevicesConnection::variantText() const
|
||||
return m_fullStatus.value("var").toString();
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::variantBackground() const
|
||||
QBrush DeviceConnection::variantBackground() const
|
||||
{
|
||||
if (!m_fullStatus.contains("var"))
|
||||
return {};
|
||||
@@ -116,7 +118,7 @@ QBrush DevicesConnection::variantBackground() const
|
||||
return red;
|
||||
}
|
||||
|
||||
QString DevicesConnection::isGoText() const
|
||||
QString DeviceConnection::isGoText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("isgo"))
|
||||
return {};
|
||||
@@ -124,7 +126,7 @@ QString DevicesConnection::isGoText() const
|
||||
return m_fullStatus.value("isgo").toBool() ? "yes" : "no";
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::isGoBackground() const
|
||||
QBrush DeviceConnection::isGoBackground() const
|
||||
{
|
||||
if (!m_fullStatus.contains("isgo"))
|
||||
return {};
|
||||
@@ -132,7 +134,7 @@ QBrush DevicesConnection::isGoBackground() const
|
||||
return m_fullStatus.value("isgo").toBool() ? blue : yellow;
|
||||
}
|
||||
|
||||
QString DevicesConnection::isAustralienText() const
|
||||
QString DeviceConnection::isAustralienText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("aus"))
|
||||
return {};
|
||||
@@ -140,7 +142,7 @@ QString DevicesConnection::isAustralienText() const
|
||||
return m_fullStatus.value("aus").toBool() ? "yes" : "no";
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::isAustralienBackground() const
|
||||
QBrush DeviceConnection::isAustralienBackground() const
|
||||
{
|
||||
if (!m_fullStatus.contains("aus"))
|
||||
return {};
|
||||
@@ -148,7 +150,7 @@ QBrush DevicesConnection::isAustralienBackground() const
|
||||
return m_fullStatus.value("aus").toBool() ? yellow : blue;
|
||||
}
|
||||
|
||||
QString DevicesConnection::resetCardText() const
|
||||
QString DeviceConnection::resetCardText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("frci"))
|
||||
return {};
|
||||
@@ -156,7 +158,7 @@ QString DevicesConnection::resetCardText() const
|
||||
return m_fullStatus.value("frci").toBool() ? "yes" : "no";
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::resetCardBackground() const
|
||||
QBrush DeviceConnection::resetCardBackground() const
|
||||
{
|
||||
if (!m_fullStatus.contains("frci"))
|
||||
return {};
|
||||
@@ -164,7 +166,7 @@ QBrush DevicesConnection::resetCardBackground() const
|
||||
return m_fullStatus.value("frci").toBool() ? green : red;
|
||||
}
|
||||
|
||||
QString DevicesConnection::connectedWifiText() const
|
||||
QString DeviceConnection::connectedWifiText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("ccw"))
|
||||
return {};
|
||||
@@ -176,7 +178,7 @@ QString DevicesConnection::connectedWifiText() const
|
||||
return apd.value("ssid").toString();
|
||||
}
|
||||
|
||||
QString DevicesConnection::projectText() const
|
||||
QString DeviceConnection::projectText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("apd"))
|
||||
return {};
|
||||
@@ -188,7 +190,7 @@ QString DevicesConnection::projectText() const
|
||||
return apd.value("project_name").toString();
|
||||
}
|
||||
|
||||
QString DevicesConnection::versionText() const
|
||||
QString DeviceConnection::versionText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("apd"))
|
||||
return {};
|
||||
@@ -200,7 +202,7 @@ QString DevicesConnection::versionText() const
|
||||
return apd.value("version").toString();
|
||||
}
|
||||
|
||||
QString DevicesConnection::idfVersionText() const
|
||||
QString DeviceConnection::idfVersionText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("apd"))
|
||||
return {};
|
||||
@@ -212,7 +214,7 @@ QString DevicesConnection::idfVersionText() const
|
||||
return apd.value("idf_ver").toString();
|
||||
}
|
||||
|
||||
QString DevicesConnection::updateText() const
|
||||
QString DeviceConnection::updateText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("ocs"))
|
||||
return {};
|
||||
@@ -241,7 +243,7 @@ QString DevicesConnection::updateText() const
|
||||
return QString::number(ocs);
|
||||
}
|
||||
|
||||
QBrush DevicesConnection::updateBackground() const
|
||||
QBrush DeviceConnection::updateBackground() const
|
||||
{
|
||||
if (!m_fullStatus.contains("ocs"))
|
||||
return {};
|
||||
@@ -259,7 +261,7 @@ QBrush DevicesConnection::updateBackground() const
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<qulonglong> DevicesConnection::uptime() const
|
||||
std::optional<qulonglong> DeviceConnection::uptime() const
|
||||
{
|
||||
if (!m_fullStatus.contains("rbt"))
|
||||
return {};
|
||||
@@ -267,7 +269,7 @@ std::optional<qulonglong> DevicesConnection::uptime() const
|
||||
return m_fullStatus.value("rbt").toULongLong();
|
||||
}
|
||||
|
||||
QString DevicesConnection::uptimeText() const
|
||||
QString DeviceConnection::uptimeText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("rbt"))
|
||||
return {};
|
||||
@@ -275,7 +277,7 @@ QString DevicesConnection::uptimeText() const
|
||||
return QString::number(m_fullStatus.value("rbt").toULongLong());
|
||||
}
|
||||
|
||||
QString DevicesConnection::currentPartition() const
|
||||
QString DeviceConnection::currentPartition() const
|
||||
{
|
||||
if (!m_fullStatus.contains("otap"))
|
||||
return {};
|
||||
@@ -287,7 +289,7 @@ QString DevicesConnection::currentPartition() const
|
||||
return otap.value("label").toString();
|
||||
}
|
||||
|
||||
std::optional<int> DevicesConnection::reboots() const
|
||||
std::optional<int> DeviceConnection::reboots() const
|
||||
{
|
||||
if (!m_fullStatus.contains("rbc"))
|
||||
return {};
|
||||
@@ -295,7 +297,7 @@ std::optional<int> DevicesConnection::reboots() const
|
||||
return m_fullStatus.value("rbc").toInt();
|
||||
}
|
||||
|
||||
QString DevicesConnection::rebootsText() const
|
||||
QString DeviceConnection::rebootsText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("rbc"))
|
||||
return {};
|
||||
@@ -303,7 +305,7 @@ QString DevicesConnection::rebootsText() const
|
||||
return QString::number(m_fullStatus.value("rbc").toInt());
|
||||
}
|
||||
|
||||
QString DevicesConnection::carStateText() const
|
||||
QString DeviceConnection::carStateText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("car"))
|
||||
return {};
|
||||
@@ -315,7 +317,7 @@ QString DevicesConnection::carStateText() const
|
||||
return QString::number(car);
|
||||
}
|
||||
|
||||
std::optional<double> DevicesConnection::energy() const
|
||||
std::optional<double> DeviceConnection::energy() const
|
||||
{
|
||||
if (!m_fullStatus.contains("eto"))
|
||||
return {};
|
||||
@@ -323,7 +325,7 @@ std::optional<double> DevicesConnection::energy() const
|
||||
return m_fullStatus.value("eto").toDouble();
|
||||
}
|
||||
|
||||
QString DevicesConnection::energyText() const
|
||||
QString DeviceConnection::energyText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("eto"))
|
||||
return {};
|
||||
@@ -331,7 +333,7 @@ QString DevicesConnection::energyText() const
|
||||
return QString("%0kWh").arg(m_fullStatus.value("eto").toDouble() / 1000.);
|
||||
}
|
||||
|
||||
QString DevicesConnection::livedataText() const
|
||||
QString DeviceConnection::livedataText() const
|
||||
{
|
||||
if (!m_fullStatus.contains("nrg"))
|
||||
return {};
|
||||
@@ -346,85 +348,94 @@ QString DevicesConnection::livedataText() const
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant DevicesConnection::getApiKey(const QString &apiKey) const
|
||||
QVariant DeviceConnection::getApiKey(const QString &apiKey) const
|
||||
{
|
||||
return m_fullStatus.value(apiKey);
|
||||
}
|
||||
|
||||
void DevicesConnection::sendMessage(const QJsonDocument &doc)
|
||||
void DeviceConnection::sendMessage(const QJsonDocument &doc)
|
||||
{
|
||||
sendMessage(QString::fromUtf8(doc.toJson()));
|
||||
}
|
||||
|
||||
void DevicesConnection::sendMessage(const QJsonObject &obj)
|
||||
void DeviceConnection::sendMessage(const QJsonObject &obj)
|
||||
{
|
||||
sendMessage(QJsonDocument{obj});
|
||||
}
|
||||
|
||||
void DevicesConnection::sendMessage(const QString &msg)
|
||||
void DeviceConnection::sendMessage(const QString &msg)
|
||||
{
|
||||
qDebug() << msg << m_websocket.errorString();
|
||||
if (const auto written = m_websocket.sendTextMessage(msg); written != msg.size())
|
||||
qCritical() << "sending message failed" << written << "(expected:" << msg.size() << ')';
|
||||
}
|
||||
|
||||
void DevicesConnection::init()
|
||||
QString DeviceConnection::errorString() const
|
||||
{
|
||||
return m_websocket.errorString();
|
||||
}
|
||||
|
||||
void DeviceConnection::init()
|
||||
{
|
||||
if (auto model = qobject_cast<DevicesModel*>(parent()))
|
||||
{
|
||||
connect(this, &DevicesConnection::wsStatusChanged, model, &DevicesModel::wsStatusChanged);
|
||||
connect(this, &DevicesConnection::statusChanged, model, &DevicesModel::statusChanged);
|
||||
connect(this, &DevicesConnection::variantChanged, model, &DevicesModel::variantChanged);
|
||||
connect(this, &DevicesConnection::isGoChanged, model, &DevicesModel::isGoChanged);
|
||||
connect(this, &DevicesConnection::isAustralienChanged, model, &DevicesModel::isAustralienChanged);
|
||||
connect(this, &DevicesConnection::resetCardChanged, model, &DevicesModel::resetCardChanged);
|
||||
connect(this, &DevicesConnection::connectedWifiChanged, model, &DevicesModel::connectedWifiChanged);
|
||||
connect(this, &DevicesConnection::projectChanged, model, &DevicesModel::projectChanged);
|
||||
connect(this, &DevicesConnection::versionChanged, model, &DevicesModel::versionChanged);
|
||||
connect(this, &DevicesConnection::idfVersionChanged, model, &DevicesModel::idfVersionChanged);
|
||||
connect(this, &DevicesConnection::updateChanged, model, &DevicesModel::updateChanged);
|
||||
connect(this, &DevicesConnection::uptimeChanged, model, &DevicesModel::uptimeChanged);
|
||||
connect(this, &DevicesConnection::currentPartitionChanged, model, &DevicesModel::currentPartitionChanged);
|
||||
connect(this, &DevicesConnection::rebootsChanged, model, &DevicesModel::rebootsChanged);
|
||||
connect(this, &DevicesConnection::carStateChanged, model, &DevicesModel::carStateChanged);
|
||||
connect(this, &DevicesConnection::energyChanged, model, &DevicesModel::energyChanged);
|
||||
connect(this, &DevicesConnection::livedataChanged, model, &DevicesModel::livedataChanged);
|
||||
connect(this, &DevicesConnection::apiKeyChanged, model, &DevicesModel::apiKeyChanged);
|
||||
connect(this, &DeviceConnection::wsStatusChanged, model, &DevicesModel::wsStatusChanged);
|
||||
connect(this, &DeviceConnection::statusChanged, model, &DevicesModel::statusChanged);
|
||||
connect(this, &DeviceConnection::variantChanged, model, &DevicesModel::variantChanged);
|
||||
connect(this, &DeviceConnection::isGoChanged, model, &DevicesModel::isGoChanged);
|
||||
connect(this, &DeviceConnection::isAustralienChanged, model, &DevicesModel::isAustralienChanged);
|
||||
connect(this, &DeviceConnection::resetCardChanged, model, &DevicesModel::resetCardChanged);
|
||||
connect(this, &DeviceConnection::connectedWifiChanged, model, &DevicesModel::connectedWifiChanged);
|
||||
connect(this, &DeviceConnection::projectChanged, model, &DevicesModel::projectChanged);
|
||||
connect(this, &DeviceConnection::versionChanged, model, &DevicesModel::versionChanged);
|
||||
connect(this, &DeviceConnection::idfVersionChanged, model, &DevicesModel::idfVersionChanged);
|
||||
connect(this, &DeviceConnection::updateChanged, model, &DevicesModel::updateChanged);
|
||||
connect(this, &DeviceConnection::uptimeChanged, model, &DevicesModel::uptimeChanged);
|
||||
connect(this, &DeviceConnection::currentPartitionChanged, model, &DevicesModel::currentPartitionChanged);
|
||||
connect(this, &DeviceConnection::rebootsChanged, model, &DevicesModel::rebootsChanged);
|
||||
connect(this, &DeviceConnection::carStateChanged, model, &DevicesModel::carStateChanged);
|
||||
connect(this, &DeviceConnection::energyChanged, model, &DevicesModel::energyChanged);
|
||||
connect(this, &DeviceConnection::livedataChanged, model, &DevicesModel::livedataChanged);
|
||||
connect(this, &DeviceConnection::apiKeyChanged, model, &DevicesModel::apiKeyChanged);
|
||||
}
|
||||
else
|
||||
qWarning() << "unexpected parent";
|
||||
|
||||
{
|
||||
auto sslConfig = m_websocket.sslConfiguration();
|
||||
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
//sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
{
|
||||
auto caCerts = QSslCertificate::fromPath(":/goe-root-ca.pem");
|
||||
if (caCerts.empty())
|
||||
qFatal("could not parse root ca");
|
||||
for (const auto &caCert : std::as_const(caCerts))
|
||||
qDebug() << caCert.issuerDisplayName();
|
||||
sslConfig.setCaCertificates(std::move(caCerts));
|
||||
}
|
||||
sslConfig.setPrivateKey(m_key);
|
||||
sslConfig.setLocalCertificate(m_cert);
|
||||
m_websocket.setSslConfiguration(sslConfig);
|
||||
m_websocket.ignoreSslErrors();
|
||||
//{
|
||||
// auto sslConfig = m_websocket.sslConfiguration();
|
||||
// sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
// //sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer);
|
||||
// {
|
||||
// auto caCerts = QSslCertificate::fromPath(":/goe-root-ca.pem");
|
||||
// if (caCerts.empty())
|
||||
// qFatal("could not parse root ca");
|
||||
// for (const auto &caCert : std::as_const(caCerts))
|
||||
// qDebug() << caCert.issuerDisplayName();
|
||||
// sslConfig.setCaCertificates(std::move(caCerts));
|
||||
// }
|
||||
// sslConfig.setPrivateKey(m_key);
|
||||
// sslConfig.setLocalCertificate(m_cert);
|
||||
// m_websocket.setSslConfiguration(sslConfig);
|
||||
// m_websocket.ignoreSslErrors();
|
||||
//}
|
||||
|
||||
connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connectedSignal);
|
||||
connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnectedSignal);
|
||||
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurredSignal);
|
||||
|
||||
connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connected);
|
||||
connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnected);
|
||||
connect(&m_websocket, &QWebSocket::stateChanged, this, &DeviceConnection::stateChanged);
|
||||
connect(&m_websocket, &QWebSocket::textMessageReceived, this, &DeviceConnection::textMessageReceived);
|
||||
connect(&m_websocket, &QWebSocket::binaryMessageReceived, this, &DeviceConnection::binaryMessageReceived);
|
||||
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurred);
|
||||
connect(&m_websocket, &QWebSocket::peerVerifyError, this, &DeviceConnection::peerVerifyError);
|
||||
connect(&m_websocket, &QWebSocket::sslErrors, this, &DeviceConnection::sslErrors);
|
||||
connect(&m_websocket, &QWebSocket::alertReceived, this, &DeviceConnection::alertReceived);
|
||||
connect(&m_websocket, &QWebSocket::handshakeInterruptedOnError, this, &DeviceConnection::handshakeInterruptedOnError);
|
||||
}
|
||||
|
||||
connect(&m_websocket, &QWebSocket::connected, this, &DevicesConnection::connected);
|
||||
connect(&m_websocket, &QWebSocket::disconnected, this, &DevicesConnection::disconnected);
|
||||
connect(&m_websocket, &QWebSocket::stateChanged, this, &DevicesConnection::stateChanged);
|
||||
connect(&m_websocket, &QWebSocket::textMessageReceived, this, &DevicesConnection::textMessageReceived);
|
||||
connect(&m_websocket, &QWebSocket::binaryMessageReceived, this, &DevicesConnection::binaryMessageReceived);
|
||||
connect(&m_websocket, &QWebSocket::errorOccurred, this, &DevicesConnection::errorOccurred);
|
||||
connect(&m_websocket, &QWebSocket::peerVerifyError, this, &DevicesConnection::peerVerifyError);
|
||||
connect(&m_websocket, &QWebSocket::sslErrors, this, &DevicesConnection::sslErrors);
|
||||
connect(&m_websocket, &QWebSocket::alertReceived, this, &DevicesConnection::alertReceived);
|
||||
connect(&m_websocket, &QWebSocket::handshakeInterruptedOnError, this, &DevicesConnection::handshakeInterruptedOnError);
|
||||
}
|
||||
|
||||
void DevicesConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
|
||||
void DeviceConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
|
||||
{
|
||||
bool variantChanged{forceChange};
|
||||
bool isGoChanged{forceChange};
|
||||
@@ -507,17 +518,17 @@ void DevicesConnection::maintainStatus(const QJsonObject &msg, bool forceChange)
|
||||
emit this->livedataChanged();
|
||||
}
|
||||
|
||||
void DevicesConnection::connected()
|
||||
void DeviceConnection::connected()
|
||||
{
|
||||
qDebug() << "called";
|
||||
}
|
||||
|
||||
void DevicesConnection::disconnected()
|
||||
void DeviceConnection::disconnected()
|
||||
{
|
||||
qDebug() << "called";
|
||||
}
|
||||
|
||||
void DevicesConnection::stateChanged(QAbstractSocket::SocketState state)
|
||||
void DeviceConnection::stateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
// qDebug() << "called" << state;
|
||||
|
||||
@@ -533,7 +544,7 @@ void DevicesConnection::stateChanged(QAbstractSocket::SocketState state)
|
||||
emit wsStatusChanged();
|
||||
}
|
||||
|
||||
void DevicesConnection::textMessageReceived(const QString &message)
|
||||
void DeviceConnection::textMessageReceived(const QString &message)
|
||||
{
|
||||
// qDebug() << "called" << message;
|
||||
|
||||
@@ -614,32 +625,32 @@ void DevicesConnection::textMessageReceived(const QString &message)
|
||||
qWarning() << "unknown message type" << msgObj;
|
||||
}
|
||||
|
||||
void DevicesConnection::binaryMessageReceived(const QByteArray &message)
|
||||
void DeviceConnection::binaryMessageReceived(const QByteArray &message)
|
||||
{
|
||||
qDebug() << "called" << message;
|
||||
}
|
||||
|
||||
void DevicesConnection::errorOccurred(QAbstractSocket::SocketError error)
|
||||
void DeviceConnection::errorOccurred(QAbstractSocket::SocketError error)
|
||||
{
|
||||
qDebug() << "called" << QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(error) << m_websocket.errorString();
|
||||
}
|
||||
|
||||
void DevicesConnection::peerVerifyError(const QSslError &error)
|
||||
void DeviceConnection::peerVerifyError(const QSslError &error)
|
||||
{
|
||||
qDebug() << "called" << error;
|
||||
}
|
||||
|
||||
void DevicesConnection::sslErrors(const QList<QSslError> &errors)
|
||||
void DeviceConnection::sslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
qDebug() << "called" << errors;
|
||||
}
|
||||
|
||||
void DevicesConnection::alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
|
||||
void DeviceConnection::alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description)
|
||||
{
|
||||
qDebug() << "called" << std::to_underlying(level) << std::to_underlying(type) << description;
|
||||
}
|
||||
|
||||
void DevicesConnection::handshakeInterruptedOnError(const QSslError &error)
|
||||
void DeviceConnection::handshakeInterruptedOnError(const QSslError &error)
|
||||
{
|
||||
qDebug() << "called" << error;
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ class QSslKey;
|
||||
class QSslCertificate;
|
||||
class QJsonObject;
|
||||
|
||||
class DevicesConnection : public QObject
|
||||
class DeviceConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DevicesConnection(const QSslKey &key, const QSslCertificate &cert, QString &&serial, QObject *parent = nullptr);
|
||||
explicit DevicesConnection(const QSslKey &key, const QSslCertificate &cert, const QString &serial, QObject *parent = nullptr);
|
||||
explicit DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent = nullptr);
|
||||
explicit DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent = nullptr);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
@@ -72,7 +72,13 @@ public:
|
||||
void sendMessage(const QJsonObject &obj);
|
||||
void sendMessage(const QString &msg);
|
||||
|
||||
QString errorString() const;
|
||||
|
||||
signals:
|
||||
void connectedSignal();
|
||||
void disconnectedSignal();
|
||||
void errorOccurredSignal(QAbstractSocket::SocketError error);
|
||||
|
||||
void responseReceived(const QString &requestId, const QJsonObject &msg);
|
||||
|
||||
void wsStatusChanged();
|
||||
@@ -112,8 +118,8 @@ private slots:
|
||||
|
||||
private:
|
||||
const QString m_serial;
|
||||
const QSslKey &m_key;
|
||||
const QSslCertificate &m_cert;
|
||||
const QByteArray m_username;
|
||||
const QByteArray m_password;
|
||||
|
||||
enum Status {
|
||||
Unknown,
|
||||
|
||||
@@ -34,12 +34,12 @@ enum {
|
||||
};
|
||||
}
|
||||
|
||||
DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
|
||||
const QSslCertificate &cert, QObject *parent) :
|
||||
DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username,
|
||||
const QByteArray &password, QObject *parent) :
|
||||
QAbstractTableModel{parent},
|
||||
m_settings{settings},
|
||||
m_key{key},
|
||||
m_cert{cert},
|
||||
m_username{username},
|
||||
m_password{password},
|
||||
m_customColumns{settings.customColumns()}
|
||||
{
|
||||
for (const auto &serial : m_settings.serials())
|
||||
@@ -47,7 +47,7 @@ DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
|
||||
if (std::none_of(std::cbegin(m_devices), std::cend(m_devices), [&serial](auto &ptr){
|
||||
return ptr->serial() == serial;
|
||||
}))
|
||||
m_devices.emplace_back(std::make_shared<DevicesConnection>(m_key, m_cert, serial, this));
|
||||
m_devices.emplace_back(std::make_shared<DeviceConnection>(m_username, m_password, serial, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ QVariant DevicesModel::data(const QModelIndex &index, int role) const
|
||||
return {};
|
||||
}
|
||||
|
||||
const DevicesConnection &device = **std::next(std::begin(m_devices), index.row());
|
||||
const DeviceConnection &device = **std::next(std::begin(m_devices), index.row());
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
@@ -332,7 +332,7 @@ bool DevicesModel::addClient(const QString &serial)
|
||||
|
||||
beginInsertRows({}, m_devices.size(), m_devices.size());
|
||||
|
||||
auto clientPtr = std::make_shared<DevicesConnection>(m_key, m_cert, serial, this);
|
||||
auto clientPtr = std::make_shared<DeviceConnection>(m_username, m_password, serial, this);
|
||||
auto client = clientPtr.get();
|
||||
m_devices.emplace_back(std::move(clientPtr));
|
||||
|
||||
@@ -343,7 +343,7 @@ bool DevicesModel::addClient(const QString &serial)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<DevicesConnection> DevicesModel::getDevice(QModelIndex index)
|
||||
std::shared_ptr<DeviceConnection> DevicesModel::getDevice(QModelIndex index)
|
||||
{
|
||||
Q_ASSERT(!index.parent().isValid());
|
||||
Q_ASSERT(index.row() >= 0 && index.row() < m_devices.size());
|
||||
@@ -352,7 +352,7 @@ std::shared_ptr<DevicesConnection> DevicesModel::getDevice(QModelIndex index)
|
||||
return device;
|
||||
}
|
||||
|
||||
std::shared_ptr<const DevicesConnection> DevicesModel::getDevice(QModelIndex index) const
|
||||
std::shared_ptr<const DeviceConnection> DevicesModel::getDevice(QModelIndex index) const
|
||||
{
|
||||
Q_ASSERT(!index.parent().isValid());
|
||||
return m_devices.at(index.row());
|
||||
@@ -500,14 +500,14 @@ void DevicesModel::apiKeyChanged(const QString &apiKey)
|
||||
|
||||
void DevicesModel::columnChanged(int column, const QList<int> &roles)
|
||||
{
|
||||
auto device = qobject_cast<DevicesConnection*>(sender());
|
||||
auto device = qobject_cast<DeviceConnection*>(sender());
|
||||
if (!device)
|
||||
{
|
||||
qWarning() << "unknown sender" << sender();
|
||||
return;
|
||||
}
|
||||
|
||||
auto iter = std::find_if(std::cbegin(m_devices), std::cend(m_devices), [&device](const std::shared_ptr<DevicesConnection> &ptr){ return device == ptr.get(); });
|
||||
auto iter = std::find_if(std::cbegin(m_devices), std::cend(m_devices), [&device](const std::shared_ptr<DeviceConnection> &ptr){ return device == ptr.get(); });
|
||||
if (iter == std::cend(m_devices))
|
||||
{
|
||||
qWarning() << "unknown sender" << device;
|
||||
|
||||
@@ -9,7 +9,7 @@ class QSslKey;
|
||||
class QSslCertificate;
|
||||
|
||||
class FlottenUpdaterSettings;
|
||||
class DevicesConnection;
|
||||
class DeviceConnection;
|
||||
|
||||
class DevicesModel : public QAbstractTableModel
|
||||
{
|
||||
@@ -18,8 +18,8 @@ class DevicesModel : public QAbstractTableModel
|
||||
using base = QAbstractTableModel;
|
||||
|
||||
public:
|
||||
explicit DevicesModel(FlottenUpdaterSettings &settings, const QSslKey &key,
|
||||
const QSslCertificate &cert, QObject *parent = nullptr);
|
||||
explicit DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username,
|
||||
const QByteArray &password, QObject *parent = nullptr);
|
||||
~DevicesModel() override;
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
@@ -30,8 +30,8 @@ public:
|
||||
|
||||
bool addClient(const QString &serial);
|
||||
|
||||
std::shared_ptr<DevicesConnection> getDevice(QModelIndex index);
|
||||
std::shared_ptr<const DevicesConnection> getDevice(QModelIndex index) const;
|
||||
std::shared_ptr<DeviceConnection> getDevice(QModelIndex index);
|
||||
std::shared_ptr<const DeviceConnection> getDevice(QModelIndex index) const;
|
||||
|
||||
void addCustomColumn(const QString &apiKey);
|
||||
bool customColumnRemovable(int section);
|
||||
@@ -64,11 +64,11 @@ public slots:
|
||||
|
||||
private:
|
||||
FlottenUpdaterSettings &m_settings;
|
||||
const QSslKey &m_key;
|
||||
const QSslCertificate &m_cert;
|
||||
const QByteArray m_username;
|
||||
const QByteArray m_password;
|
||||
void columnChanged(int column, const QList<int> &roles = QList<int>());
|
||||
|
||||
std::vector<std::shared_ptr<DevicesConnection>> m_devices;
|
||||
std::vector<std::shared_ptr<DeviceConnection>> m_devices;
|
||||
|
||||
QStringList m_customColumns;
|
||||
};
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
#include "flottenupdatersettings.h"
|
||||
|
||||
QByteArray FlottenUpdaterSettings::privateKey() const
|
||||
QByteArray FlottenUpdaterSettings::username() const
|
||||
{
|
||||
return value("privateKey").toByteArray();
|
||||
return value("username").toByteArray();
|
||||
}
|
||||
|
||||
void FlottenUpdaterSettings::setPrivateKey(const QByteArray &key)
|
||||
void FlottenUpdaterSettings::setUsername(const QByteArray &username)
|
||||
{
|
||||
setValue("privateKey", key);
|
||||
setValue("username", username);
|
||||
}
|
||||
|
||||
QByteArray FlottenUpdaterSettings::privateCert() const
|
||||
QByteArray FlottenUpdaterSettings::password() const
|
||||
{
|
||||
return value("privateCert").toByteArray();
|
||||
return value("password").toByteArray();
|
||||
}
|
||||
|
||||
void FlottenUpdaterSettings::setPrivateCert(const QByteArray &cert)
|
||||
void FlottenUpdaterSettings::setPassword(const QByteArray &password)
|
||||
{
|
||||
setValue("privateCert", cert);
|
||||
setValue("password", password);
|
||||
}
|
||||
|
||||
QStringList FlottenUpdaterSettings::customColumns() const
|
||||
|
||||
@@ -9,11 +9,11 @@ class FlottenUpdaterSettings : public QSettings
|
||||
public:
|
||||
using QSettings::QSettings;
|
||||
|
||||
QByteArray privateKey() const;
|
||||
void setPrivateKey(const QByteArray &key);
|
||||
QByteArray username() const;
|
||||
void setUsername(const QByteArray &key);
|
||||
|
||||
QByteArray privateCert() const;
|
||||
void setPrivateCert(const QByteArray &cert);
|
||||
QByteArray password() const;
|
||||
void setPassword(const QByteArray &cert);
|
||||
|
||||
QStringList customColumns() const;
|
||||
void setCustomColumns(const QStringList &customColumns);
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
#include "importcertificatedialog.h"
|
||||
#include "ui_importcertificatedialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QSslSocket>
|
||||
|
||||
#ifdef HAS_OPENSSL
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAS_OPENSSL
|
||||
namespace {
|
||||
OSSL_PROVIDER *legacy{};
|
||||
}
|
||||
#endif
|
||||
|
||||
ImportCertificateDialog::ImportCertificateDialog(QWidget *parent) :
|
||||
QDialog{parent},
|
||||
m_ui{std::make_unique<Ui::ImportCertificateDialog>()}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->pushButtonImport, &QPushButton::clicked, this, &ImportCertificateDialog::loadP12File);
|
||||
connect(m_ui->plainTextEditKey, &QPlainTextEdit::textChanged, this, &ImportCertificateDialog::keyChanged);
|
||||
connect(m_ui->plainTextEditCert, &QPlainTextEdit::textChanged, this, &ImportCertificateDialog::certChanged);
|
||||
|
||||
m_ui->labelSupportsSslValue->setText(QSslSocket::supportsSsl() ? tr("Yes") : tr("No"));
|
||||
m_ui->labelSslLibraryVersionValue->setText(QSslSocket::sslLibraryVersionString());
|
||||
m_ui->labelSslLibraryBuildVersionValue->setText(QSslSocket::sslLibraryBuildVersionString());
|
||||
const auto &availableBackends = QSslSocket::availableBackends();
|
||||
for (const auto &backend : availableBackends)
|
||||
m_ui->comboBoxSslBackend->addItem(backend);
|
||||
m_ui->comboBoxSslBackend->setCurrentText(QSslSocket::activeBackend());
|
||||
connect(m_ui->comboBoxSslBackend, &QComboBox::currentIndexChanged,
|
||||
this, &ImportCertificateDialog::updateActiveBackend);
|
||||
}
|
||||
|
||||
ImportCertificateDialog::~ImportCertificateDialog() = default;
|
||||
|
||||
void ImportCertificateDialog::accept()
|
||||
{
|
||||
if (m_key.isNull())
|
||||
return;
|
||||
if (m_cert.isNull())
|
||||
return;
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ImportCertificateDialog::loadP12File()
|
||||
{
|
||||
auto selected = QFileDialog::getOpenFileName(this, tr("Select certificate..."), {}, "Certificates (*.p12)");
|
||||
if (selected.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file{selected};
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open file!"), tr("Could not open file!") + "\n\n" + file.errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok{};
|
||||
QString passwordStr = QInputDialog::getText(this, tr("Please enter password"), tr("Certificate password:"), QLineEdit::PasswordEchoOnEdit, {}, &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
auto password = passwordStr.toUtf8();
|
||||
|
||||
QSslKey key;
|
||||
QSslCertificate cert;
|
||||
QList<QSslCertificate> certChain;
|
||||
|
||||
#ifdef HAS_OPENSSL
|
||||
if (QSslSocket::activeBackend() == "openssl" && !legacy)
|
||||
{
|
||||
legacy = OSSL_PROVIDER_load(NULL, "legacy");
|
||||
if (!legacy)
|
||||
QMessageBox::warning(this, tr("Failed to load openssl legacy provider!"), tr("Failed to load openssl legacy provider!"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!QSslCertificate::importPkcs12(&file, &key, &cert, &certChain, password))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("Possible reasons: openssl has a problem, the file is corrupt/invalid or the password is incorrect."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.isNull())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("The key seems to be invalid."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cert.isNull())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Failed processing certificate!"), tr("Failed processing certificate!") + "\n\n" + tr("The cert seems to be invalid."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_key = std::move(key);
|
||||
m_cert = std::move(cert);
|
||||
|
||||
{
|
||||
QSignalBlocker blocker{m_ui->plainTextEditKey};
|
||||
m_ui->plainTextEditKey->setPlainText(m_key.toPem());
|
||||
}
|
||||
|
||||
{
|
||||
auto palette = m_ui->plainTextEditKey->palette();
|
||||
palette.setBrush(QPalette::Base, QColor{200, 255, 200});
|
||||
palette.setBrush(QPalette::Window, QColor{200, 255, 200});
|
||||
m_ui->plainTextEditKey->setPalette(palette);
|
||||
}
|
||||
|
||||
{
|
||||
QSignalBlocker blocker{m_ui->plainTextEditCert};
|
||||
m_ui->plainTextEditCert->setPlainText(m_cert.toPem());
|
||||
}
|
||||
|
||||
{
|
||||
auto palette = m_ui->plainTextEditCert->palette();
|
||||
palette.setBrush(QPalette::Base, QColor{200, 255, 200});
|
||||
palette.setBrush(QPalette::Window, QColor{200, 255, 200});
|
||||
m_ui->plainTextEditCert->setPalette(palette);
|
||||
}
|
||||
}
|
||||
|
||||
void ImportCertificateDialog::keyChanged()
|
||||
{
|
||||
m_key = QSslKey{m_ui->plainTextEditKey->toPlainText().toUtf8(), QSsl::KeyAlgorithm::Rsa, QSsl::Pem};
|
||||
|
||||
auto palette = m_ui->plainTextEditKey->palette();
|
||||
palette.setBrush(QPalette::Base, m_key.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
|
||||
palette.setBrush(QPalette::Window, m_key.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
|
||||
m_ui->plainTextEditKey->setPalette(palette);
|
||||
}
|
||||
|
||||
void ImportCertificateDialog::certChanged()
|
||||
{
|
||||
m_cert = QSslCertificate{m_ui->plainTextEditCert->toPlainText().toUtf8()};
|
||||
|
||||
auto palette = m_ui->plainTextEditCert->palette();
|
||||
palette.setBrush(QPalette::Base, m_cert.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
|
||||
palette.setBrush(QPalette::Window, m_cert.isNull() ? QColor{255, 200, 200} : QColor{200, 255, 200});
|
||||
m_ui->plainTextEditCert->setPalette(palette);
|
||||
}
|
||||
|
||||
void ImportCertificateDialog::updateActiveBackend()
|
||||
{
|
||||
if (!QSslSocket::setActiveBackend(m_ui->comboBoxSslBackend->currentText()))
|
||||
QMessageBox::warning(this, tr("Could not change active backend"), tr("Could not change active backend"));
|
||||
m_ui->comboBoxSslBackend->setCurrentText(QSslSocket::activeBackend());
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSslKey>
|
||||
#include <QSslCertificate>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Ui { class ImportCertificateDialog; }
|
||||
|
||||
class ImportCertificateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImportCertificateDialog(QWidget *parent = nullptr);
|
||||
~ImportCertificateDialog();
|
||||
|
||||
const QSslKey &privateKey() const { return m_key; }
|
||||
const QSslCertificate &privateCert() const { return m_cert; }
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
private slots:
|
||||
void loadP12File();
|
||||
void keyChanged();
|
||||
void certChanged();
|
||||
void updateActiveBackend();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Ui::ImportCertificateDialog> m_ui;
|
||||
|
||||
QSslKey m_key;
|
||||
QSslCertificate m_cert;
|
||||
};
|
||||
@@ -1,184 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImportCertificateDialog</class>
|
||||
<widget class="QDialog" name="ImportCertificateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>459</width>
|
||||
<height>429</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Import Certificate</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSupportsSsl">
|
||||
<property name="text">
|
||||
<string>Supports Ssl:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelSupportsSslValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelSslLibraryVersion">
|
||||
<property name="text">
|
||||
<string>Ssl Library Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelSslLibraryVersionValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelSslLibraryBuildVersion">
|
||||
<property name="text">
|
||||
<string>Ssl Library Build Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelSslLibraryBuildVersionValue">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelSslBackend">
|
||||
<property name="text">
|
||||
<string>Ssl Backend:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>comboBoxSslBackend</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxSslBackend"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelAutomaticImport">
|
||||
<property name="text">
|
||||
<string>Automatic Import:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pushButtonImport</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="pushButtonImport">
|
||||
<property name="text">
|
||||
<string>Load p12 file...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelPrivateKey">
|
||||
<property name="text">
|
||||
<string>Private Key:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>plainTextEditKey</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPlainTextEdit" name="plainTextEditKey">
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="labelPrivateCert">
|
||||
<property name="text">
|
||||
<string>Private Cert:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>plainTextEditCert</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPlainTextEdit" name="plainTextEditCert">
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWarning">
|
||||
<property name="text">
|
||||
<string>Warning: Your private key and cert will be stored on this machine, but can later be erased from the main window.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ImportCertificateDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ImportCertificateDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "importcredentialsdialog.h"
|
||||
#include "ui_importcredentialsdialog.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "deviceconnection.h"
|
||||
|
||||
ImportCredentialsDialog::ImportCredentialsDialog(QWidget *parent) :
|
||||
QDialog{parent},
|
||||
m_ui{std::make_unique<Ui::ImportCredentialsDialog>()}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
ImportCredentialsDialog::~ImportCredentialsDialog() = default;
|
||||
|
||||
QByteArray ImportCredentialsDialog::username() const
|
||||
{
|
||||
return m_ui->lineEditUsername->text().toUtf8();
|
||||
}
|
||||
|
||||
QByteArray ImportCredentialsDialog::password() const
|
||||
{
|
||||
return m_ui->lineEditPassword->text().toUtf8();
|
||||
}
|
||||
|
||||
void ImportCredentialsDialog::accept()
|
||||
{
|
||||
if (username().isEmpty() ||
|
||||
password().isEmpty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Please fill out all fields!"), tr("Please fill out all fields!"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_ui->lineEditUsername->setEnabled(false);
|
||||
m_ui->lineEditPassword->setEnabled(false);
|
||||
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save))
|
||||
button->setEnabled(false);
|
||||
|
||||
m_testConnection = std::make_unique<DeviceConnection>(username(), password(), "123456");
|
||||
connect(m_testConnection.get(), &DeviceConnection::connectedSignal,
|
||||
this, &ImportCredentialsDialog::connected);
|
||||
connect(m_testConnection.get(), &DeviceConnection::disconnectedSignal,
|
||||
this, &ImportCredentialsDialog::disconnected);
|
||||
connect(m_testConnection.get(), &DeviceConnection::errorOccurredSignal,
|
||||
this, &ImportCredentialsDialog::errorOccurred);
|
||||
m_testConnection->start();
|
||||
}
|
||||
|
||||
void ImportCredentialsDialog::connected()
|
||||
{
|
||||
qDebug() << "called";
|
||||
|
||||
QDialog::accept();
|
||||
|
||||
finishTestConnection();
|
||||
}
|
||||
|
||||
void ImportCredentialsDialog::disconnected()
|
||||
{
|
||||
qDebug() << "called";
|
||||
|
||||
finishTestConnection();
|
||||
}
|
||||
|
||||
void ImportCredentialsDialog::errorOccurred(QAbstractSocket::SocketError error)
|
||||
{
|
||||
Q_ASSERT(m_testConnection);
|
||||
QMessageBox::warning(this,
|
||||
tr("Problem verifying credentials!"),
|
||||
QString("%0\n\n%1")
|
||||
.arg(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(error))
|
||||
.arg(m_testConnection->errorString())
|
||||
);
|
||||
}
|
||||
|
||||
void ImportCredentialsDialog::finishTestConnection()
|
||||
{
|
||||
Q_ASSERT(m_testConnection);
|
||||
|
||||
m_ui->lineEditUsername->setEnabled(true);
|
||||
m_ui->lineEditPassword->setEnabled(true);
|
||||
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save))
|
||||
button->setEnabled(true);
|
||||
|
||||
m_testConnection.release()->deleteLater();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractSocket>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Ui { class ImportCredentialsDialog; }
|
||||
class DeviceConnection;
|
||||
|
||||
class ImportCredentialsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImportCredentialsDialog(QWidget *parent = nullptr);
|
||||
~ImportCredentialsDialog();
|
||||
|
||||
QByteArray username() const;
|
||||
QByteArray password() const;
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
private slots:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void errorOccurred(QAbstractSocket::SocketError error);
|
||||
|
||||
private:
|
||||
void finishTestConnection();
|
||||
|
||||
const std::unique_ptr<Ui::ImportCredentialsDialog> m_ui;
|
||||
std::unique_ptr<DeviceConnection> m_testConnection;
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImportCredentialsDialog</class>
|
||||
<widget class="QDialog" name="ImportCredentialsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>442</width>
|
||||
<height>164</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Import Credentials</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTitle">
|
||||
<property name="text">
|
||||
<string>Please enter your credentials to access solalaweb.com:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Please create an app password in <a href="https://auth.go-e.com/if/user/#/settings;{%22page%22:%22page-tokens%22}">our SSO</a>.</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelUsername">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditUsername</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelPassword">
|
||||
<property name="text">
|
||||
<string>App-Password:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lineEditPassword</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditUsername"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditPassword"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ImportCredentialsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ImportCredentialsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
+14
-37
@@ -1,14 +1,9 @@
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
#include <QSslKey>
|
||||
#include <QSslCertificate>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QSslSocket>
|
||||
#endif
|
||||
|
||||
#include "flottenupdatersettings.h"
|
||||
#include "importcertificatedialog.h"
|
||||
#include "importcredentialsdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -36,50 +31,32 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
FlottenUpdaterSettings settings;
|
||||
QByteArray keyBuf = settings.privateKey();
|
||||
QByteArray certBuf = settings.privateCert();
|
||||
QSslKey key{keyBuf, QSsl::KeyAlgorithm::Rsa, QSsl::Pem};
|
||||
QSslCertificate cert{certBuf};
|
||||
QByteArray username = settings.username();
|
||||
QByteArray password = settings.password();
|
||||
|
||||
if (keyBuf.isEmpty())
|
||||
goto loadCert;
|
||||
if (username.isEmpty())
|
||||
goto loadCredentials;
|
||||
|
||||
if (certBuf.isEmpty())
|
||||
goto loadCert;
|
||||
|
||||
if (key.isNull())
|
||||
{
|
||||
QMessageBox::warning(nullptr,
|
||||
QCoreApplication::translate("main", "Could not parse private key!"),
|
||||
QCoreApplication::translate("main", "Could not parse private key!"));
|
||||
goto loadCert;
|
||||
}
|
||||
|
||||
if (cert.isNull())
|
||||
{
|
||||
QMessageBox::warning(nullptr,
|
||||
QCoreApplication::translate("main", "Could not parse private cert!"),
|
||||
QCoreApplication::translate("main", "Could not parse private cert!"));
|
||||
goto loadCert;
|
||||
}
|
||||
if (password.isEmpty())
|
||||
goto loadCredentials;
|
||||
|
||||
goto showMainWindow;
|
||||
|
||||
{
|
||||
loadCert:
|
||||
ImportCertificateDialog dialog;
|
||||
loadCredentials:
|
||||
ImportCredentialsDialog dialog;
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return 0;
|
||||
|
||||
key = dialog.privateKey();
|
||||
cert = dialog.privateCert();
|
||||
settings.setPrivateKey(key.toPem());
|
||||
settings.setPrivateCert(cert.toPem());
|
||||
username = dialog.username();
|
||||
password = dialog.password();
|
||||
settings.setUsername(username);
|
||||
settings.setPassword(password);
|
||||
}
|
||||
|
||||
showMainWindow:
|
||||
|
||||
MainWindow mainWindow{settings, key, cert};
|
||||
MainWindow mainWindow{settings, username, password};
|
||||
mainWindow.show();
|
||||
|
||||
return app.exec();
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
#include "setarbitraryapikeydialog.h"
|
||||
#include "addserialsrangedialog.h"
|
||||
|
||||
MainWindow::MainWindow(FlottenUpdaterSettings &settings, const QSslKey &key,
|
||||
const QSslCertificate &cert, QWidget *parent) :
|
||||
MainWindow::MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username,
|
||||
const QByteArray &password, QWidget *parent) :
|
||||
QMainWindow{parent},
|
||||
m_ui{std::make_unique<Ui::MainWindow>()},
|
||||
m_settings{settings},
|
||||
m_model{std::make_unique<DevicesModel>(settings, key, cert, this)},
|
||||
m_model{std::make_unique<DevicesModel>(settings, username, password, this)},
|
||||
m_proxyModel{std::make_unique<QSortFilterProxyModel>(this)}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
@@ -146,7 +146,7 @@ void MainWindow::contextMenuRequested(const QPoint &pos)
|
||||
[&](const QModelIndex &index){ return m_proxyModel->mapToSource(index); });
|
||||
|
||||
// get all the devices for selected indices
|
||||
std::vector<std::shared_ptr<DevicesConnection>> devices;
|
||||
std::vector<std::shared_ptr<DeviceConnection>> devices;
|
||||
devices.reserve(selectedRows.size());
|
||||
std::transform(std::begin(selectedRows), std::end(selectedRows), std::back_inserter(devices),
|
||||
[&](const QModelIndex &index){ auto device = m_model->getDevice(index); Q_ASSERT(device); return device; });
|
||||
|
||||
@@ -18,8 +18,8 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(FlottenUpdaterSettings &settings, const QSslKey &key,
|
||||
const QSslCertificate &cert, QWidget *parent = nullptr);
|
||||
explicit MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username,
|
||||
const QByteArray &password, QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "deviceconnection.h"
|
||||
#include "requestmodel.h"
|
||||
|
||||
RequestDialog::RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QWidget *parent) :
|
||||
RequestDialog::RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QWidget *parent) :
|
||||
QDialog{parent},
|
||||
m_ui{std::make_unique<Ui::RequestDialog>()},
|
||||
m_model{std::make_unique<RequestModel>(std::move(msg), std::move(devices), this)}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <memory>
|
||||
|
||||
class QJsonObject;
|
||||
class DevicesConnection;
|
||||
class DeviceConnection;
|
||||
class RequestModel;
|
||||
|
||||
namespace Ui { class RequestDialog; }
|
||||
@@ -15,7 +15,7 @@ class RequestDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QWidget *parent = nullptr);
|
||||
explicit RequestDialog(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QWidget *parent = nullptr);
|
||||
~RequestDialog();
|
||||
|
||||
private:
|
||||
|
||||
@@ -21,7 +21,7 @@ enum {
|
||||
QString getRandomString();
|
||||
}
|
||||
|
||||
RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QObject *parent) :
|
||||
RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QObject *parent) :
|
||||
QAbstractTableModel{parent}
|
||||
{
|
||||
m_requests.reserve(devices.size());
|
||||
@@ -33,7 +33,7 @@ RequestModel::RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<Device
|
||||
.requestId = getRandomString()
|
||||
};
|
||||
|
||||
connect(request.device.get(), &DevicesConnection::responseReceived, this, &RequestModel::responseReceived);
|
||||
connect(request.device.get(), &DeviceConnection::responseReceived, this, &RequestModel::responseReceived);
|
||||
|
||||
{
|
||||
QJsonObject msg2 = msg;
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#include <memory>
|
||||
|
||||
class QJsonObject;
|
||||
class DevicesConnection;
|
||||
class DeviceConnection;
|
||||
|
||||
class RequestModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DevicesConnection>> &&devices, QObject *parent = nullptr);
|
||||
explicit RequestModel(QJsonObject &&msg, std::vector<std::shared_ptr<DeviceConnection>> &&devices, QObject *parent = nullptr);
|
||||
~RequestModel() override;
|
||||
|
||||
// QAbstractItemModel interface
|
||||
@@ -27,7 +27,7 @@ private slots:
|
||||
|
||||
private:
|
||||
struct Request {
|
||||
std::shared_ptr<DevicesConnection> device;
|
||||
std::shared_ptr<DeviceConnection> device;
|
||||
QString requestId;
|
||||
enum class Status { Pending, Failed, Succeeded };
|
||||
Status status{Status::Pending};
|
||||
|
||||
Reference in New Issue
Block a user