Skip to content

Commit

Permalink
[buteo-sync-plugins-social] Allow sync to continue on delete event er…
Browse files Browse the repository at this point in the history
…ror. Contributes to JB#51507

If an error is triggered due to an event being deleted that's already
been deleted from the server, this change allows the sync to continue.

This ensures the account doesn't have to be recreated to fix the issue
on the client.
  • Loading branch information
llewelld committed Nov 26, 2020
1 parent 19021b6 commit f9b5f8d
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/google/google-calendars/google-calendars.pri
@@ -1,6 +1,11 @@
CONFIG += link_pkgconfig
PKGCONFIG += libmkcal-qt5 libkcalcoren-qt5
SOURCES += $$PWD/googlecalendarsyncadaptor.cpp
HEADERS += $$PWD/googlecalendarsyncadaptor.h $$PWD/googlecalendarincidencecomparator.h
SOURCES += \
$$PWD/googlecalendarsyncadaptor.cpp \
$$PWD/googlecalendarsyncerror.cpp
HEADERS += \
$$PWD/googlecalendarsyncadaptor.h \
$$PWD/googlecalendarincidencecomparator.h \
$$PWD/googlecalendarsyncerror.h
INCLUDEPATH += $$PWD

10 changes: 10 additions & 0 deletions src/google/google-calendars/googlecalendarsyncadaptor.cpp
Expand Up @@ -21,6 +21,7 @@

#include "googlecalendarsyncadaptor.h"
#include "googlecalendarincidencecomparator.h"
#include "googlecalendarsyncerror.h"
#include "trace.h"

#include <QtCore/QUrlQuery>
Expand Down Expand Up @@ -2203,6 +2204,15 @@ void GoogleCalendarSyncAdaptor::upsyncFinishedHandler()
// TODO: is there some way to detect whether I am the organizer/owner of the event?
if (reply->error() == QNetworkReply::ContentOperationNotPermittedError) {
SOCIALD_LOG_TRACE("Ignoring 403 due to shared calendar resource");
} else if (httpCode == 410) {
const GoogleCalendarSyncError error(replyData);
if (error.firstReason() == QStringLiteral("deleted")) {
// HTTP 410 GONE "deleted"
// The event was already deleted on the server, so continue as normal
} else {
errorDumpStr(QString::fromUtf8(replyData));
m_syncSucceeded[accountId] = false;
}
} else {
m_syncSucceeded[accountId] = false;
}
Expand Down
76 changes: 76 additions & 0 deletions src/google/google-calendars/googlecalendarsyncerror.cpp
@@ -0,0 +1,76 @@
#include <QJsonDocument>
#include <QJsonObject>

#include "socialnetworksyncadaptor.h"
#include "trace.h"

#include "googlecalendarsyncerror.h"

GoogleCalendarSyncError::GoogleCalendarSyncError()
: m_valid(false)
, m_code(0)
{
}

GoogleCalendarSyncError::GoogleCalendarSyncError(QByteArray const &replyData)
: m_valid(false)
, m_code(0)
{
QJsonDocument jsonDocument = QJsonDocument::fromJson(replyData);
if (!jsonDocument.isEmpty()
&& jsonDocument.isObject()
&& jsonDocument.object().contains(QStringLiteral("error"))) {
QJsonObject error = jsonDocument.object().value(QStringLiteral("error")).toObject();

if (error.contains(QStringLiteral("code"))
&& error.value(QStringLiteral("code")).isDouble()
&& error.contains(QStringLiteral("errors"))
&& error.value(QStringLiteral("errors")).isArray()) {
m_valid = true;
m_code = error.value(QStringLiteral("code")).toInt();
m_message = error.value(QStringLiteral("message")).toString();
QJsonArray errors = error.value(QStringLiteral("errors")).toArray();

for (QJsonValue errorItem : errors) {
if (errorItem.isObject()) {
QJsonObject item = errorItem.toObject();
GoogleCalendarSyncErrorInfo details;
details.m_domain = item.value(QStringLiteral("domain")).toString();
details.m_reason = item.value(QStringLiteral("reason")).toString();
details.m_message = item.value(QStringLiteral("message")).toString();
details.m_locationType = item.value(QStringLiteral("locationType")).toString();
details.m_location = item.value(QStringLiteral("location")).toString();
m_error.append(details);
}
}

if (m_error.isEmpty()) {
SOCIALD_LOG_ERROR("no error block when parsing returned json");
}
} else {
SOCIALD_LOG_ERROR("essential components missing when parsing error json");
}
} else {
SOCIALD_LOG_ERROR("error parsing returned json");
}
}

bool GoogleCalendarSyncError::isValid() const
{
return m_valid;
}

int GoogleCalendarSyncError::code() const
{
return m_code;
}

QString GoogleCalendarSyncError::message() const
{
return m_message;
}

QString GoogleCalendarSyncError::firstReason() const
{
return m_error.empty() ? QString() : m_error[0].m_reason;
}
38 changes: 38 additions & 0 deletions src/google/google-calendars/googlecalendarsyncerror.h
@@ -0,0 +1,38 @@
#ifndef GOOGLECALENDARSYNCERROR_H
#define GOOGLECALENDARSYNCERROR_H

#include <QByteArray>
#include <QString>
#include <QList>

class GoogleCalendarSyncErrorInfo {
public:
QString m_domain;
QString m_reason;
QString m_message;
QString m_locationType;
QString m_location;
};

// GoogleCalendarSyncError captures the json data
// representing a request error. See:
// https://developers.google.com/calendar/v3/errors
class GoogleCalendarSyncError
{
public:
explicit GoogleCalendarSyncError();
GoogleCalendarSyncError(QByteArray const &replyData);

bool isValid() const;
int code() const;
QString message() const;
QString firstReason() const;

public:
bool m_valid;
int m_code;
QString m_message;
QList<GoogleCalendarSyncErrorInfo> m_error;
};

#endif // GOOGLECALENDARSYNCERROR_H

0 comments on commit f9b5f8d

Please sign in to comment.