@@ -179,6 +179,8 @@ add_library(neochat STATIC
|
|||||||
threepidaddhelper.h
|
threepidaddhelper.h
|
||||||
jobs/neochatadd3pidjob.cpp
|
jobs/neochatadd3pidjob.cpp
|
||||||
jobs/neochatadd3pidjob.h
|
jobs/neochatadd3pidjob.h
|
||||||
|
identityserverhelper.cpp
|
||||||
|
identityserverhelper.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||||
|
|||||||
154
src/identityserverhelper.cpp
Normal file
154
src/identityserverhelper.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include "identityserverhelper.h"
|
||||||
|
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
#include <KLocalizedString>
|
||||||
|
|
||||||
|
#include <Quotient/networkaccessmanager.h>
|
||||||
|
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
|
IdentityServerHelper::IdentityServerHelper(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NeoChatConnection *IdentityServerHelper::connection() const
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityServerHelper::setConnection(NeoChatConnection *connection)
|
||||||
|
{
|
||||||
|
if (m_connection == connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_connection != nullptr) {
|
||||||
|
m_connection->disconnect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_connection = connection;
|
||||||
|
Q_EMIT connectionChanged();
|
||||||
|
Q_EMIT currentServerChanged();
|
||||||
|
|
||||||
|
connect(m_connection, &NeoChatConnection::accountDataChanged, this, [this](const QString &type) {
|
||||||
|
if (type == QLatin1String("m.identity_server")) {
|
||||||
|
Q_EMIT currentServerChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IdentityServerHelper::currentServer() const
|
||||||
|
{
|
||||||
|
if (m_connection == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_connection->hasAccountData(QLatin1String("m.identity_server"))) {
|
||||||
|
return i18nc("@info", "No identity server configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto url = m_connection->accountData(QLatin1String("m.identity_server"))->contentPart<QUrl>(QLatin1String("base_url"));
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
return i18nc("@info", "No identity server configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IdentityServerHelper::hasCurrentServer() const
|
||||||
|
{
|
||||||
|
if (m_connection == nullptr && !m_connection->hasAccountData(QLatin1String("m.identity_server"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto url = m_connection->accountData(QLatin1String("m.identity_server"))->contentPart<QUrl>(QLatin1String("base_url"));
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IdentityServerHelper::url() const
|
||||||
|
{
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityServerHelper::setUrl(const QString &url)
|
||||||
|
{
|
||||||
|
if (url == m_url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_url = url;
|
||||||
|
Q_EMIT urlChanged();
|
||||||
|
|
||||||
|
checkUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentityServerHelper::IdServerStatus IdentityServerHelper::status() const
|
||||||
|
{
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityServerHelper::checkUrl()
|
||||||
|
{
|
||||||
|
if (m_idServerCheckRequest != nullptr) {
|
||||||
|
m_idServerCheckRequest->abort();
|
||||||
|
m_idServerCheckRequest.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_url == currentServer()) {
|
||||||
|
m_status = Match;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_url.isEmpty()) {
|
||||||
|
m_status = Valid;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto requestUrl = QUrl(m_url + QStringLiteral("/_matrix/identity/v2"));
|
||||||
|
if (!(requestUrl.scheme() == QStringLiteral("https") || requestUrl.scheme() == QStringLiteral("http"))) {
|
||||||
|
m_status = Invalid;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest request(requestUrl);
|
||||||
|
m_idServerCheckRequest = Quotient::NetworkAccessManager::instance()->get(request);
|
||||||
|
connect(m_idServerCheckRequest, &QNetworkReply::finished, this, [this]() {
|
||||||
|
if (m_idServerCheckRequest->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||||
|
m_status = Valid;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
} else {
|
||||||
|
m_status = Invalid;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityServerHelper::setIdentityServer()
|
||||||
|
{
|
||||||
|
if (m_url == currentServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_connection->setAccountData(QLatin1String("m.identity_server"), {{QLatin1String("base_url"), m_url}});
|
||||||
|
m_status = Ready;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityServerHelper::clearIdentityServer()
|
||||||
|
{
|
||||||
|
if (currentServer().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_connection->setAccountData(QLatin1String("m.identity_server"), {{QLatin1String("base_url"), QString()}});
|
||||||
|
m_status = Ready;
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
}
|
||||||
103
src/identityserverhelper.h
Normal file
103
src/identityserverhelper.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include <Quotient/jobs/basejob.h>
|
||||||
|
|
||||||
|
class NeoChatConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class IdentityServerHelper
|
||||||
|
*
|
||||||
|
* This class is designed to help the process of setting an identity server for the account.
|
||||||
|
* It will manage the various stages of verification and authentication.
|
||||||
|
*/
|
||||||
|
class IdentityServerHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The connection to add a 3PID to.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current identity server.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString currentServer READ currentServer NOTIFY currentServerChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Whether an identity server is currently configured.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool hasCurrentServer READ hasCurrentServer NOTIFY currentServerChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The URL for the desired server.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The current status.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(IdServerStatus status READ status NOTIFY statusChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief The current status for adding an identity server
|
||||||
|
*/
|
||||||
|
enum IdServerStatus {
|
||||||
|
Ready, /**< The process is ready to start. I.e. there is no ongoing attempt to set a new server. */
|
||||||
|
Valid, /**< The server URL is valid. */
|
||||||
|
Invalid, /**< The server URL is invalid. */
|
||||||
|
Match, /**< The server URL is the one that is already configured. */
|
||||||
|
Other, /**< An unknown problem occurred. */
|
||||||
|
};
|
||||||
|
Q_ENUM(IdServerStatus)
|
||||||
|
|
||||||
|
explicit IdentityServerHelper(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
|
[[nodiscard]] QString currentServer() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasCurrentServer() const;
|
||||||
|
|
||||||
|
[[nodiscard]] QString url() const;
|
||||||
|
void setUrl(const QString &url);
|
||||||
|
|
||||||
|
[[nodiscard]] IdServerStatus status() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the current URL as the user's identity server.
|
||||||
|
*
|
||||||
|
* Will do nothing if the URL isn't a valid identity server.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void setIdentityServer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the user's identity server.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void clearIdentityServer();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void connectionChanged();
|
||||||
|
void currentServerChanged();
|
||||||
|
void urlChanged();
|
||||||
|
void statusChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
|
||||||
|
IdServerStatus m_status = Ready;
|
||||||
|
QString m_url;
|
||||||
|
|
||||||
|
QPointer<QNetworkReply> m_idServerCheckRequest;
|
||||||
|
|
||||||
|
void checkUrl();
|
||||||
|
};
|
||||||
@@ -207,6 +207,15 @@ FormCard.FormCardPage {
|
|||||||
title: i18n("Phone Numbers")
|
title: i18n("Phone Numbers")
|
||||||
medium: "msisdn"
|
medium: "msisdn"
|
||||||
}
|
}
|
||||||
|
FormCard.FormHeader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
title: i18n("Identity Server")
|
||||||
|
}
|
||||||
|
FormCard.FormCard {
|
||||||
|
IdentityServerDelegate {
|
||||||
|
connection: root.connection
|
||||||
|
}
|
||||||
|
}
|
||||||
FormCard.FormHeader {
|
FormCard.FormHeader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
title: i18n("Server Information")
|
title: i18n("Server Information")
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ qt_add_qml_module(settings
|
|||||||
DevicesCard.qml
|
DevicesCard.qml
|
||||||
DeviceDelegate.qml
|
DeviceDelegate.qml
|
||||||
EmoticonFormCard.qml
|
EmoticonFormCard.qml
|
||||||
|
IdentityServerDelegate.qml
|
||||||
IgnoredUsersDialog.qml
|
IgnoredUsersDialog.qml
|
||||||
NotificationRuleItem.qml
|
NotificationRuleItem.qml
|
||||||
PasswordSheet.qml
|
PasswordSheet.qml
|
||||||
|
|||||||
142
src/settings/IdentityServerDelegate.qml
Normal file
142
src/settings/IdentityServerDelegate.qml
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.kirigamiaddons.formcard as FormCard
|
||||||
|
|
||||||
|
import org.kde.neochat
|
||||||
|
|
||||||
|
FormCard.AbstractFormDelegate {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property NeoChatConnection connection
|
||||||
|
|
||||||
|
property bool editServerUrl: false
|
||||||
|
|
||||||
|
text: identityServerHelper.currentServer
|
||||||
|
|
||||||
|
onClicked: editIdServerButton.toggle()
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
QQC2.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: !root.editServerUrl
|
||||||
|
text: root.text
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
Kirigami.ActionTextField {
|
||||||
|
id: editUrlField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.editServerUrl
|
||||||
|
|
||||||
|
Accessible.description: i18n("New identity server url")
|
||||||
|
|
||||||
|
rightActions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
text: i18nc("@action:button", "Cancel editing identity server url")
|
||||||
|
icon.name: "edit-delete-remove"
|
||||||
|
onTriggered: editIdServerButton.toggle()
|
||||||
|
},
|
||||||
|
Kirigami.Action {
|
||||||
|
enabled: identityServerHelper.status == IdentityServerHelper.Valid
|
||||||
|
text: i18nc("@action:button", "Confirm new identity server url")
|
||||||
|
icon.name: "checkmark"
|
||||||
|
visible: editUrlField.text !== root.text
|
||||||
|
onTriggered: {
|
||||||
|
identityServerHelper.setIdentityServer();
|
||||||
|
editUrlField.text = "";
|
||||||
|
editIdServerButton.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
identityServerHelper.setIdentityServer()
|
||||||
|
editUrlField.text = "";
|
||||||
|
editIdServerButton.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kirigami.InlineMessage {
|
||||||
|
id: editUrlStatus
|
||||||
|
visible: root.editServerUrl && text.length > 0 && !warningTimer.running
|
||||||
|
Layout.topMargin: visible ? Kirigami.Units.smallSpacing : 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: switch(identityServerHelper.status) {
|
||||||
|
case IdentityServerHelper.Invalid:
|
||||||
|
return i18n("The entered url is not a valid identity server");
|
||||||
|
case IdentityServerHelper.Match:
|
||||||
|
return i18n("The entered url is already configured as your identity server");
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
type: switch(identityServerHelper.status) {
|
||||||
|
case IdentityServerHelper.Invalid:
|
||||||
|
return Kirigami.MessageType.Error;
|
||||||
|
case IdentityServerHelper.Match:
|
||||||
|
return Kirigami.MessageType.Warning;
|
||||||
|
default:
|
||||||
|
return Kirigami.MessageType.Information;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: warningTimer
|
||||||
|
interval: 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QQC2.ToolButton {
|
||||||
|
id: editIdServerButton
|
||||||
|
display: QQC2.AbstractButton.IconOnly
|
||||||
|
text: i18nc("@action:button", "Edit identity server url")
|
||||||
|
icon.name: "document-edit"
|
||||||
|
checkable: true
|
||||||
|
onCheckedChanged: {
|
||||||
|
root.editServerUrl = !root.editServerUrl;
|
||||||
|
if (checked) {
|
||||||
|
editUrlField.forceActiveFocus();
|
||||||
|
} else {
|
||||||
|
editUrlField.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QQC2.ToolTip {
|
||||||
|
text: editIdServerButton.text
|
||||||
|
delay: Kirigami.Units.toolTipDelay
|
||||||
|
visible: editIdServerButton.hovered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QQC2.ToolButton {
|
||||||
|
id: removeIdServerButton
|
||||||
|
visible: identityServerHelper.hasCurrentServer
|
||||||
|
display: QQC2.AbstractButton.IconOnly
|
||||||
|
text: i18nc("@action:button", "Remove identity server")
|
||||||
|
icon.name: "edit-delete-remove"
|
||||||
|
onClicked: {
|
||||||
|
identityServerHelper.clearIdentityServer();
|
||||||
|
editUrlField.text = "";
|
||||||
|
if (editIdServerButton.checked) {
|
||||||
|
editIdServerButton.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QQC2.ToolTip {
|
||||||
|
text: removeIdServerButton.text
|
||||||
|
delay: Kirigami.Units.toolTipDelay
|
||||||
|
visible: removeIdServerButton.hovered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentityServerHelper {
|
||||||
|
id: identityServerHelper
|
||||||
|
connection: root.connection
|
||||||
|
url: editUrlField.text
|
||||||
|
onUrlChanged: warningTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user