mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-31 21:13:23 +00:00
mobile: add ability to delete cloud account
Apple store rules require this. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
941aaf5b65
commit
32bc034f41
9 changed files with 159 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
mobile: allow cloud account deletion (Apple app store requirement)
|
||||||
|
|
||||||
---
|
---
|
||||||
* Always add new entries at the very top of this file above other existing entries and this note.
|
* Always add new entries at the very top of this file above other existing entries and this note.
|
||||||
|
|
|
@ -17,6 +17,7 @@ CloudStorageAuthenticate::CloudStorageAuthenticate(QObject *parent) :
|
||||||
#define CLOUDBACKENDSTORAGE CLOUDURL + "/storage"
|
#define CLOUDBACKENDSTORAGE CLOUDURL + "/storage"
|
||||||
#define CLOUDBACKENDVERIFY CLOUDURL + "/verify"
|
#define CLOUDBACKENDVERIFY CLOUDURL + "/verify"
|
||||||
#define CLOUDBACKENDUPDATE CLOUDURL + "/update"
|
#define CLOUDBACKENDUPDATE CLOUDURL + "/update"
|
||||||
|
#define CLOUDBACKENDDELETE CLOUDURL + "/delete-account"
|
||||||
|
|
||||||
QNetworkReply* CloudStorageAuthenticate::backend(const QString& email,const QString& password,const QString& pin,const QString& newpasswd)
|
QNetworkReply* CloudStorageAuthenticate::backend(const QString& email,const QString& password,const QString& pin,const QString& newpasswd)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +51,34 @@ QNetworkReply* CloudStorageAuthenticate::backend(const QString& email,const QStr
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QNetworkReply* CloudStorageAuthenticate::deleteAccount(const QString& email, const QString& password)
|
||||||
|
{
|
||||||
|
QString payload(email + QChar(' ') + password);
|
||||||
|
QNetworkRequest *request = new QNetworkRequest(QUrl(CLOUDBACKENDDELETE));
|
||||||
|
request->setRawHeader("Accept", "text/xml, text/plain");
|
||||||
|
request->setRawHeader("User-Agent", userAgent.toUtf8());
|
||||||
|
request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
|
||||||
|
reply = manager()->post(*request, qPrintable(payload));
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &CloudStorageAuthenticate::deleteFinished);
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &CloudStorageAuthenticate::sslErrors);
|
||||||
|
connect(reply, &QNetworkReply::errorOccurred, this, &CloudStorageAuthenticate::uploadError);
|
||||||
|
#else
|
||||||
|
connect(reply, SIGNAL(finished()), this, SLOT(deleteFinished()));
|
||||||
|
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
|
||||||
|
SLOT(uploadError(QNetworkReply::NetworkError)));
|
||||||
|
#endif
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloudStorageAuthenticate::deleteFinished()
|
||||||
|
{
|
||||||
|
QString cloudAuthReply(reply->readAll());
|
||||||
|
qDebug() << "Completed connection with cloud storage backend, response" << cloudAuthReply;
|
||||||
|
emit finishedDelete();
|
||||||
|
}
|
||||||
|
|
||||||
void CloudStorageAuthenticate::uploadFinished()
|
void CloudStorageAuthenticate::uploadFinished()
|
||||||
{
|
{
|
||||||
static QString myLastError;
|
static QString myLastError;
|
||||||
|
|
|
@ -9,15 +9,18 @@ class CloudStorageAuthenticate : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QNetworkReply* backend(const QString& email,const QString& password,const QString& pin = QString(),const QString& newpasswd = QString());
|
QNetworkReply* backend(const QString& email,const QString& password,const QString& pin = QString(),const QString& newpasswd = QString());
|
||||||
|
QNetworkReply* deleteAccount(const QString& email, const QString &passwd);
|
||||||
explicit CloudStorageAuthenticate(QObject *parent);
|
explicit CloudStorageAuthenticate(QObject *parent);
|
||||||
signals:
|
signals:
|
||||||
void finishedAuthenticate();
|
void finishedAuthenticate();
|
||||||
|
void finishedDelete();
|
||||||
void passwordChangeSuccessful();
|
void passwordChangeSuccessful();
|
||||||
private
|
private
|
||||||
slots:
|
slots:
|
||||||
void uploadError(QNetworkReply::NetworkError error);
|
void uploadError(QNetworkReply::NetworkError error);
|
||||||
void sslErrors(const QList<QSslError> &errorList);
|
void sslErrors(const QList<QSslError> &errorList);
|
||||||
void uploadFinished();
|
void uploadFinished();
|
||||||
|
void deleteFinished();
|
||||||
private:
|
private:
|
||||||
QNetworkReply *reply;
|
QNetworkReply *reply;
|
||||||
QString userAgent;
|
QString userAgent;
|
||||||
|
|
75
mobile-widgets/qml/DeleteAccount.qml
Normal file
75
mobile-widgets/qml/DeleteAccount.qml
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
import QtQuick 2.6
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import org.kde.kirigami 2.4 as Kirigami
|
||||||
|
import org.subsurfacedivelog.mobile 1.0
|
||||||
|
|
||||||
|
Kirigami.ScrollablePage {
|
||||||
|
id: deleteAccountPage
|
||||||
|
property int pageWidth: deleteAccountPage.width - deleteAccountPage.leftPadding - deleteAccountPage.rightPadding
|
||||||
|
title: qsTr("Delete Subsurface Cloud Account")
|
||||||
|
background: Rectangle { color: subsurfaceTheme.backgroundColor }
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
width: deleteAccountPage.width
|
||||||
|
Layout.margins: Kirigami.Units.gridUnit / 2
|
||||||
|
|
||||||
|
Kirigami.Heading {
|
||||||
|
text: qsTr("Delete Subsurface Cloud Account")
|
||||||
|
color: subsurfaceTheme.textColor
|
||||||
|
Layout.topMargin: Kirigami.Units.gridUnit
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: pageWidth
|
||||||
|
wrapMode: TextEdit.NoWrap
|
||||||
|
fontSizeMode: Text.Fit
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Heading {
|
||||||
|
text: qsTr("Deleting your Subsurface Cloud account is permanent.\n") +
|
||||||
|
qsTr("There is no way to undo this action.")
|
||||||
|
level: 4
|
||||||
|
color: subsurfaceTheme.textColor
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.topMargin: Kirigami.Units.largeSpacing * 3
|
||||||
|
Layout.maximumWidth: pageWidth
|
||||||
|
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
|
||||||
|
anchors.horizontalCenter: parent.Center
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Heading {
|
||||||
|
text: PrefCloudStorage.cloud_storage_email
|
||||||
|
level: 4
|
||||||
|
color: subsurfaceTheme.textColor
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.topMargin: Kirigami.Units.largeSpacing * 3
|
||||||
|
Layout.maximumWidth: pageWidth
|
||||||
|
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
|
||||||
|
anchors.horizontalCenter: parent.Center
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TemplateButton {
|
||||||
|
id: deleteCloudAccount
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("delete cloud account")
|
||||||
|
onClicked: {
|
||||||
|
manager.appendTextToLog("request to delete account confirmed")
|
||||||
|
manager.deleteAccount()
|
||||||
|
rootItem.returnTopPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateButton {
|
||||||
|
id: dontDeleteCloudAccount
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("never mind")
|
||||||
|
onClicked: {
|
||||||
|
manager.appendTextToLog("request to delete account cancelled")
|
||||||
|
rootItem.returnTopPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,15 @@ TemplatePage {
|
||||||
text: describe[Backend.cloud_verification_status]
|
text: describe[Backend.cloud_verification_status]
|
||||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
|
||||||
}
|
}
|
||||||
|
TemplateButton {
|
||||||
|
id: deleteCloudAccount
|
||||||
|
enabled: Backend.cloud_verification_status !== Enums.CS_NOCLOUD
|
||||||
|
text: qsTr("Delete Account")
|
||||||
|
onClicked: {
|
||||||
|
manager.appendTextToLog("requesting account deletion");
|
||||||
|
showPage(deleteAccount)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TemplateLine {
|
TemplateLine {
|
||||||
visible: sectionGeneral.isExpanded
|
visible: sectionGeneral.isExpanded
|
||||||
|
|
|
@ -783,6 +783,10 @@ if you have network connectivity and want to sync your data to cloud storage."),
|
||||||
id: settingsWindow
|
id: settingsWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeleteAccount {
|
||||||
|
id: deleteAccount
|
||||||
|
}
|
||||||
|
|
||||||
CopySettings {
|
CopySettings {
|
||||||
id: settingsCopyWindow
|
id: settingsCopyWindow
|
||||||
visible: false
|
visible: false
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<!-- ********** qml ********** -->
|
<!-- ********** qml ********** -->
|
||||||
<file>About.qml</file>
|
<file>About.qml</file>
|
||||||
<file>CloudCredentials.qml</file>
|
<file>CloudCredentials.qml</file>
|
||||||
|
<file>DeleteAccount.qml</file>
|
||||||
<file>DiveDetails.qml</file>
|
<file>DiveDetails.qml</file>
|
||||||
<file>DiveDetailsEdit.qml</file>
|
<file>DiveDetailsEdit.qml</file>
|
||||||
<file>DiveDetailsView.qml</file>
|
<file>DiveDetailsView.qml</file>
|
||||||
|
|
|
@ -725,6 +725,42 @@ bool QMLManager::verifyCredentials(QString email, QString password, QString pin)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QMLManager::deleteAccount()
|
||||||
|
{
|
||||||
|
QString email(prefs.cloud_storage_email);
|
||||||
|
QString passwd(prefs.cloud_storage_password);
|
||||||
|
if (email.isEmpty() || passwd.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setStartPageText(tr("Deleting cloud account..."));
|
||||||
|
appendTextToLog(QStringLiteral("user requested that we delete cloud account for email %1").arg(email));
|
||||||
|
CloudStorageAuthenticate *csa = new CloudStorageAuthenticate(this);
|
||||||
|
csa->deleteAccount(email, passwd);
|
||||||
|
// let's wait here for the signal to avoid too many more nested functions
|
||||||
|
QTimer myTimer;
|
||||||
|
myTimer.setSingleShot(true);
|
||||||
|
QEventLoop loop;
|
||||||
|
connect(csa, &CloudStorageAuthenticate::finishedDelete, &loop, &QEventLoop::quit);
|
||||||
|
connect(&myTimer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||||
|
myTimer.start(prefs.cloud_timeout * 3 * 1000); // give it extra time
|
||||||
|
loop.exec();
|
||||||
|
if (!myTimer.isActive()) {
|
||||||
|
// got no response from the server
|
||||||
|
setStartPageText(RED_FONT + tr("No response from cloud server to delete account") + END_FONT);
|
||||||
|
appendTextToLog(QStringLiteral("no response from cloud server to delete account"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
myTimer.stop();
|
||||||
|
appendTextToLog(QStringLiteral("deleted the account"));
|
||||||
|
qPrefCloudStorage::set_cloud_storage_email("");
|
||||||
|
qPrefCloudStorage::set_cloud_storage_email_encoded("");
|
||||||
|
qPrefCloudStorage::set_cloud_storage_password("");
|
||||||
|
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NOCLOUD);
|
||||||
|
set_filename(qPrintable(nocloud_localstorage()));
|
||||||
|
setStartPageText(tr("Cloud storage account deleted."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void QMLManager::loadDivesWithValidCredentials()
|
void QMLManager::loadDivesWithValidCredentials()
|
||||||
{
|
{
|
||||||
QString url;
|
QString url;
|
||||||
|
|
|
@ -180,6 +180,7 @@ public slots:
|
||||||
void saveChangesCloud(bool forceRemoteSync, bool fromUndo = false);
|
void saveChangesCloud(bool forceRemoteSync, bool fromUndo = false);
|
||||||
void selectDive(int id);
|
void selectDive(int id);
|
||||||
void deleteDive(int id);
|
void deleteDive(int id);
|
||||||
|
void deleteAccount();
|
||||||
void toggleDiveInvalid(int id);
|
void toggleDiveInvalid(int id);
|
||||||
void copyDiveData(int id);
|
void copyDiveData(int id);
|
||||||
void pasteDiveData(int id);
|
void pasteDiveData(int id);
|
||||||
|
|
Loading…
Add table
Reference in a new issue