diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07c9b0a33..1828bcdd0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -126,8 +126,6 @@ add_library(neochat STATIC registration.cpp neochatconnection.cpp neochatconnection.h - jobs/neochatdeactivateaccountjob.cpp - jobs/neochatdeactivateaccountjob.h jobs/neochatgetcommonroomsjob.cpp jobs/neochatgetcommonroomsjob.h mediasizehelper.cpp diff --git a/src/jobs/neochatdeactivateaccountjob.cpp b/src/jobs/neochatdeactivateaccountjob.cpp deleted file mode 100644 index 8fc90810d..000000000 --- a/src/jobs/neochatdeactivateaccountjob.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Tobias Fella -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "neochatdeactivateaccountjob.h" - -using namespace Quotient; - -NeoChatDeactivateAccountJob::NeoChatDeactivateAccountJob(const std::optional &auth) - : BaseJob(HttpVerb::Post, u"DisableDeviceJob"_s, "_matrix/client/v3/account/deactivate") -{ - QJsonObject data; - addParam(data, u"auth"_s, auth); - setRequestData(data); -} diff --git a/src/jobs/neochatdeactivateaccountjob.h b/src/jobs/neochatdeactivateaccountjob.h deleted file mode 100644 index 327c04761..000000000 --- a/src/jobs/neochatdeactivateaccountjob.h +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Tobias Fella -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -class NeoChatDeactivateAccountJob : public Quotient::BaseJob -{ -public: - explicit NeoChatDeactivateAccountJob(const std::optional &auth = {}); -}; diff --git a/src/neochatconnection.cpp b/src/neochatconnection.cpp index a001d5172..1ae4e8432 100644 --- a/src/neochatconnection.cpp +++ b/src/neochatconnection.cpp @@ -6,7 +6,6 @@ #include #include -#include "jobs/neochatdeactivateaccountjob.h" #include "neochatconfig.h" #include "neochatroom.h" #include "spacehierarchycache.h" @@ -142,6 +141,8 @@ void NeoChatConnection::connectSignals() connect(job, &GetVersionsJob::success, this, [this, job] { m_canCheckMutualRooms = job->unstableFeatures().contains("uk.half-shot.msc2666.query_mutual_rooms"_L1); Q_EMIT canCheckMutualRoomsChanged(); + m_canEraseData = job->unstableFeatures().contains("org.matrix.msc4025"_L1) || job->versions().count("v1.10"_L1); + Q_EMIT canEraseDataChanged(); }); }, Qt::SingleShotConnection); @@ -255,20 +256,20 @@ QString NeoChatConnection::label() const return accountDataJson("org.kde.neochat.account_label"_L1)["account_label"_L1].toString(); } -void NeoChatConnection::deactivateAccount(const QString &password) +void NeoChatConnection::deactivateAccount(const QString &password, const bool erase) { - auto job = callApi(); - connect(job, &BaseJob::result, this, [this, job, password] { + auto job = callApi(); + connect(job, &BaseJob::result, this, [this, job, password, erase] { if (job->error() == 103) { QJsonObject replyData = job->jsonData(); - QJsonObject authData; - authData["session"_L1] = replyData["session"_L1]; - authData["password"_L1] = password; - authData["type"_L1] = "m.login.password"_L1; - authData["user"_L1] = user()->id(); + AuthenticationData authData; + authData.session = replyData["session"_L1].toString(); + authData.authInfo["password"_L1] = password; + authData.type = "m.login.password"_L1; + authData.authInfo["user"_L1] = user()->id(); QJsonObject identifier = {{"type"_L1, "m.id.user"_L1}, {"user"_L1, user()->id()}}; - authData["identifier"_L1] = identifier; - auto innerJob = callApi(authData); + authData.authInfo["identifier"_L1] = identifier; + auto innerJob = callApi(authData, QString{}, erase); connect(innerJob, &BaseJob::success, this, [this]() { logout(false); }); @@ -548,4 +549,9 @@ KeyImport::Error NeoChatConnection::exportMegolmSessions(const QString &passphra return KeyImport::Success; } +bool NeoChatConnection::canEraseData() const +{ + return m_canEraseData; +} + #include "moc_neochatconnection.cpp" diff --git a/src/neochatconnection.h b/src/neochatconnection.h index 79054994c..519f77c7d 100644 --- a/src/neochatconnection.h +++ b/src/neochatconnection.h @@ -87,6 +87,11 @@ class NeoChatConnection : public Quotient::Connection */ Q_PROPERTY(bool canCheckMutualRooms READ canCheckMutualRooms NOTIFY canCheckMutualRoomsChanged) + /** + * @brief Whether the server supports erasing user data when deactivating the account. This checks for MSC4025. + */ + Q_PROPERTY(bool canEraseData READ canEraseData NOTIFY canEraseDataChanged) + public: /** * @brief Defines the status after an attempt to change the password on an account. @@ -104,6 +109,7 @@ public: Q_INVOKABLE void logout(bool serverSideLogout); Q_INVOKABLE QVariantList getSupportedRoomVersions() const; bool canCheckMutualRooms() const; + bool canEraseData() const; /** * @brief Change the password for an account. @@ -123,7 +129,7 @@ public: [[nodiscard]] QString label() const; void setLabel(const QString &label); - Q_INVOKABLE void deactivateAccount(const QString &password); + Q_INVOKABLE void deactivateAccount(const QString &password, bool erase); ThreePIdModel *threePIdModel() const; @@ -194,6 +200,7 @@ Q_SIGNALS: void userConsentRequired(QUrl url); void badgeNotificationCountChanged(NeoChatConnection *connection, int count); void canCheckMutualRoomsChanged(); + void canEraseDataChanged(); /** * @brief Request a message be shown to the user of the given type. @@ -223,4 +230,5 @@ private: QCache m_linkPreviewers; bool m_canCheckMutualRooms = false; + bool m_canEraseData = false; }; diff --git a/src/qml/ConfirmDeactivateAccountDialog.qml b/src/qml/ConfirmDeactivateAccountDialog.qml index a45eb138b..f7e933b4b 100644 --- a/src/qml/ConfirmDeactivateAccountDialog.qml +++ b/src/qml/ConfirmDeactivateAccountDialog.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later import QtQuick +import QtQuick.Layouts import QtQuick.Controls as QQC2 import org.kde.kirigamiaddons.formcard as FormCard @@ -18,12 +19,21 @@ Kirigami.PromptDialog { dialogType: Kirigami.PromptDialog.Warning - mainItem: FormCard.FormTextFieldDelegate { - id: passwordField - label: i18nc("@label:textbox", "Password") - echoMode: TextInput.Password - horizontalPadding: 0 - bottomPadding: 0 + mainItem: ColumnLayout { + FormCard.FormTextFieldDelegate { + id: passwordField + label: i18nc("@label:textbox", "Password") + echoMode: TextInput.Password + horizontalPadding: 0 + bottomPadding: 0 + } + + FormCard.FormCheckDelegate { + id: eraseDelegate + text: i18nc("@label:checkbox", "Erase Data") + description: i18nc("@info", "Request your server to delete as much user data as possible.") + visible: connection.canEraseData + } } footer: QQC2.DialogButtonBox { @@ -34,7 +44,7 @@ Kirigami.PromptDialog { icon.name: "emblem-warning" enabled: passwordField.text.length > 0 onClicked: { - root.connection.deactivateAccount(passwordField.text); + root.connection.deactivateAccount(passwordField.text, eraseDelegate.checked); root.closeDialog(); } }