diff --git a/CMakeLists.txt b/CMakeLists.txt index 480393f41..f8ce1656a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,167 +1,172 @@ cmake_minimum_required(VERSION 3.0) set(PIM_VERSION "5.9.40") set(KDEPIM_RUNTIME_VERSION_NUMBER ${PIM_VERSION}) project(kdepim-runtime VERSION ${KDEPIM_RUNTIME_VERSION_NUMBER}) if (POLICY CMP0053) cmake_policy(SET CMP0053 NEW) endif() ############### KDEPIM-Runtime version ################ # KDEPIM_RUNTIME_VERSION # Version scheme: "x.y.z build". # # x is the version number. # y is the major release number. # z is the minor release number. # # "x.y.z" follow the kdelibs version kdepim is released with. # # If "z" is 0, it the version is "x.y" # # KDEPIM_DEV_VERSION # is empty for final versions. For development versions "build" is # something like "pre", "", "alpha2", "beta1", "beta2", "rc1", "rc2". # # Examples in chronological order: # # 3.0 # 3.0.1 # 3.1 # 3.1 beta1 # 3.1 beta2 # 3.1 rc1 # 3.1 # 3.1.1 # 3.2 pre # 3.2 set(KDEPIM_DEV_VERSION alpha) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) set(KDEPIM_DEV_VERSION " ${KDEPIM_DEV_VERSION}") endif() set(KDEPIM_RUNTIME_VERSION "${KDEPIM_RUNTIME_VERSION_NUMBER}${KDEPIM_DEV_VERSION}") configure_file(kdepim-runtime-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdepim-runtime-version.h @ONLY) set(KF5_VERSION "5.50.0") find_package(ECM ${KF5_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${kdepim-runtime_SOURCE_DIR}/cmake/ ${ECM_MODULE_PATH}) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(ECMQtDeclareLoggingCategory) include(GenerateExportHeader) set(QT_REQUIRED_VERSION "5.9.0") set(KDEPIMRUNTIME_LIB_VERSION "${KDEPIM_RUNTIME_VERSION_NUMBER}") set(KDEPIMRUNTIME_LIB_SOVERSION "5") set(AKONADI_VERSION "5.9.40") set(KCONTACTS_LIB_VERSION "5.9.40") set(KCALENDARCORE_LIB_VERSION "5.9.40") set(IDENTITYMANAGEMENT_LIB_VERSION "5.9.40") set(KMAILTRANSPORT_LIB_VERSION "5.9.40") set(CALENDARUTILS_LIB_VERSION "5.9.40") set(KDAV_LIB_VERSION "5.9.40") set(KIMAP_LIB_VERSION "5.9.40") set(KMBOX_LIB_VERSION "5.9.40") set(AKONADICALENDAR_LIB_VERSION "5.9.40") set(KONTACTINTERFACE_LIB_VERSION "5.9.40") set(AKONADIKALARM_LIB_VERSION "5.9.40") set(KMIME_LIB_VERSION "5.9.40") set(XMLRPCCLIENT_LIB_VERSION "5.9.40") set(KCONTACTS_LIB_VERSION "5.9.40") set(AKONADIMIME_LIB_VERSION "5.9.40") set(AKONADICONTACT_LIB_VERSION "5.9.40") set(AKONADINOTE_LIB_VERSION "5.9.40") set(PIMCOMMON_LIB_VERSION "5.9.40") set(KGAPI_LIB_VERSION "5.9.40") set( SharedMimeInfo_MINIMUM_VERSION "1.3" ) find_package(SharedMimeInfo ${SharedMimeInfo_MINIMUM_VERSION} REQUIRED) find_package(Sasl2) set_package_properties(Sasl2 PROPERTIES TYPE REQUIRED) # QT5 package find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Network Widgets Test XmlPatterns DBus WebEngineWidgets) -find_package(Qt5 OPTIONAL_COMPONENTS TextToSpeech) +find_package(Qt5 OPTIONAL_COMPONENTS TextToSpeech NetworkAuth) if (NOT Qt5TextToSpeech_FOUND) message(STATUS "Qt5TextToSpeech not found, speech feature will be disabled") else() add_definitions(-DHAVE_TEXTTOSPEECH) endif() +if (NOT Qt5NetworkAuth_FOUND) + message(STATUS "Qt5NetworkAuth not found, OAuth2 authentication will not be supported") +else() + add_definitions(-DHAVE_NETWORKAUTH) +endif() # KF5 package find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5NotifyConfig ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ItemModels ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WindowSystem ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_VERSION} CONFIG REQUIRED) # for KPluralHandlingSpinBox find_package(KF5Notifications ${KF5_VERSION} CONFIG REQUIRED) # pop3 find_package(KF5DocTools ${KF5_VERSION} CONFIG REQUIRED) # pop3 find_package(KF5Holidays ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KDELibs4Support ${KF5_VERSION} CONFIG REQUIRED) # KdepimLibs package find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KPimKDAV ${KDAV_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADICONTACT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Contacts ${KCONTACTS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AlarmCalendar ${AKONADIKALARM_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarCore ${KCALENDARCORE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mbox ${KMBOX_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IMAP ${KIMAP_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiNotes ${AKONADINOTE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiCalendar ${AKONADICALENDAR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimCommon ${PIMCOMMON_LIB_VERSION} CONFIG REQUIRED) find_package(KPimGAPI ${KGAPI_LIB_VERSION} CONFIG REQUIRED) option(KDEPIM_RUN_ISOLATED_TESTS "Run the isolated tests." FALSE) add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) #add_definitions( -DQT_DISABLE_DEPRECATED_BEFORE=0x060000 ) add_subdirectory(resources) add_subdirectory(agents) add_subdirectory(defaultsetup) add_subdirectory(kioslave) add_subdirectory(migration) add_subdirectory(doc) ## install the MIME type spec file for KDEPIM specific MIME types install(FILES kdepim-mime.xml DESTINATION ${KDE_INSTALL_MIMEDIR}) update_xdg_mimetypes(${KDE_INSTALL_MIMEDIR}) install( FILES kdepim-runtime.renamecategories kdepim-runtime.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES ) diff --git a/resources/ews/ewsclient/CMakeLists.txt b/resources/ews/ewsclient/CMakeLists.txt index 71fb5c990..fb552d61a 100644 --- a/resources/ews/ewsclient/CMakeLists.txt +++ b/resources/ews/ewsclient/CMakeLists.txt @@ -1,92 +1,103 @@ # -# Copyright (C) 2015-2017 Krzysztof Nowicki +# Copyright (C) 2015-2018 Krzysztof Nowicki # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License # along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. include_directories(${CMAKE_CURRENT_BINARY_DIR}/../) set(EWSCLIENT_SRCS ewsattachment.cpp ewsattendee.cpp ewsclient.cpp ewscreatefolderrequest.cpp ewscreateitemrequest.cpp ewsdeletefolderrequest.cpp ewsdeleteitemrequest.cpp ewseffectiverights.cpp ewseventrequestbase.cpp ewsfindfolderrequest.cpp ewsfinditemrequest.cpp ewsfolder.cpp ewsfoldershape.cpp ewsgeteventsrequest.cpp ewsgetstreamingeventsrequest.cpp ewsgetfolderrequest.cpp ewsgetitemrequest.cpp ewsid.cpp ewsitem.cpp ewsitembase.cpp ewsitemshape.cpp ewsjob.cpp ewsmailbox.cpp ewsmovefolderrequest.cpp ewsmoveitemrequest.cpp ewsoccurrence.cpp ewspoxautodiscoverrequest.cpp ewspropertyfield.cpp ewsrecurrence.cpp ewsrequest.cpp ewsserverversion.cpp ewssubscriberequest.cpp ewssyncfolderhierarchyrequest.cpp ewssyncfolderitemsrequest.cpp ewstypes.cpp ewsunsubscriberequest.cpp ewsupdatefolderrequest.cpp ewsupdateitemrequest.cpp ewsxml.cpp ewsclient_debug.cpp) +if (Qt5NetworkAuth_FOUND) + list(APPEND EWSCLIENT_SRCS + ewsoauth.cpp) +endif () + ecm_qt_declare_logging_category(EWSCLIENT_SRCS HEADER ewscli_debug.h IDENTIFIER EWSCLI_LOG CATEGORY_NAME org.kde.pim.ews.client) ecm_qt_declare_logging_category(EWSCLIENT_SRCS HEADER ewscli_proto_debug.h IDENTIFIER EWSCLI_PROTO_LOG CATEGORY_NAME org.kde.pim.ews.client.proto DEFAULT_SEVERITY Warning) ecm_qt_declare_logging_category(EWSCLIENT_SRCS HEADER ewscli_req_debug.h IDENTIFIER EWSCLI_REQUEST_LOG CATEGORY_NAME org.kde.pim.ews.client.request DEFAULT_SEVERITY Warning) ecm_qt_declare_logging_category(EWSCLIENT_SRCS HEADER ewscli_failedreq_debug.h IDENTIFIER EWSCLI_FAILEDREQUEST_LOG CATEGORY_NAME org.kde.pim.ews.client.failedrequest DEFAULT_SEVERITY Warning) add_library(ewsclient STATIC ${EWSCLIENT_SRCS}) -target_link_libraries(ewsclient +target_link_libraries(ewsclient Qt5::Network KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets KF5::KIONTLM KF5::Codecs KF5::Mime KF5::CalendarCore) + +if (Qt5NetworkAuth_FOUND) + target_link_libraries(ewsclient + Qt5::NetworkAuth + Qt5::WebEngineWidgets) +endif () diff --git a/resources/ews/ewsclient/ewsoauth.cpp b/resources/ews/ewsclient/ewsoauth.cpp new file mode 100644 index 000000000..def9a82cb --- /dev/null +++ b/resources/ews/ewsclient/ewsoauth.cpp @@ -0,0 +1,282 @@ +/* + Copyright (C) 2018 Krzysztof Nowicki + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "ewsoauth.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ewsclient_debug.h" + +static const auto o365AuthorizationUrl = QUrl(QStringLiteral("https://login.microsoftonline.com/common/oauth2/authorize")); +static const auto o365AccessTokenUrl = QUrl(QStringLiteral("https://login.microsoftonline.com/common/oauth2/token")); +static const auto o365FakeUserAgent = QStringLiteral("Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36"); +static const auto o365Resource = QStringLiteral("https%3A%2F%2Foutlook.office365.com%2F"); + +class EwsOAuthUrlSchemeHandler final : public QWebEngineUrlSchemeHandler +{ + Q_OBJECT +public: + EwsOAuthUrlSchemeHandler(QObject *parent = Q_NULLPTR) : QWebEngineUrlSchemeHandler(parent) {}; + ~EwsOAuthUrlSchemeHandler() override = default; + void requestStarted(QWebEngineUrlRequestJob *request) override; +signals: + void returnUriReceived(QUrl url); +}; + +class EwsOAuthReplyHandler final : public QOAuthOobReplyHandler +{ + Q_OBJECT +public: + EwsOAuthReplyHandler(QObject *parent, const QString &returnUri) + : QOAuthOobReplyHandler(parent), mReturnUri(returnUri) {}; + ~EwsOAuthReplyHandler() override = default; + + QString callback() const override { return mReturnUri; }; +private: + const QString mReturnUri; +}; + +class EwsOAuthRequestInterceptor final : public QWebEngineUrlRequestInterceptor +{ + Q_OBJECT +public: + EwsOAuthRequestInterceptor(QObject *parent, const QString &redirectUri) + : QWebEngineUrlRequestInterceptor(parent), mRedirectUri(redirectUri) + { + }; + + ~EwsOAuthRequestInterceptor() override = default; + + void interceptRequest(QWebEngineUrlRequestInfo &info) override; +Q_SIGNALS: + void redirectUriIntercepted(const QUrl &url); +private: + const QString mRedirectUri; +}; + +class EwsOAuthPrivate final : public QObject +{ + Q_OBJECT +public: + EwsOAuthPrivate(EwsOAuth *parent, const QString &email, const QString &appId, const QString &redirectUri); + ~EwsOAuthPrivate() override = default; + + void authenticate(); + + void modifyParametersFunction(QAbstractOAuth::Stage stage, QVariantMap *parameters); + void authorizeWithBrowser(const QUrl &url); + void redirectUriIntercepted(const QUrl &url); + void granted(); + void error(const QString &error, const QString &errorDescription, const QUrl &uri); + + QWebEngineView mWebView; + QWebEngineProfile mWebProfile; + QWebEnginePage mWebPage; + QOAuth2AuthorizationCodeFlow mOAuth2; + EwsOAuthReplyHandler mReplyHandler; + EwsOAuthRequestInterceptor mRequestInterceptor; + EwsOAuthUrlSchemeHandler mSchemeHandler; + QString mToken; + const QString mEmail; + const QString mRedirectUri; + EwsOAuth::State mState; + QPointer mWebDialog; + + EwsOAuth *q_ptr = nullptr; + Q_DECLARE_PUBLIC(EwsOAuth) +}; + + +void EwsOAuthUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) +{ + returnUriReceived(request->requestUrl()); +} + + +void EwsOAuthRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) +{ + const auto url = info.requestUrl(); + + qCDebug(EWSCLI_LOG) << QStringLiteral("Intercepted browser navigation to ") << url; + + if (url.toString(QUrl::RemoveQuery) == mRedirectUri) { + qCDebug(EWSCLI_LOG) << QStringLiteral("Found redirect URI - blocking request"); + + redirectUriIntercepted(url); + info.block(true); + } +} + +EwsOAuthPrivate::EwsOAuthPrivate(EwsOAuth *parent, const QString &email, const QString &appId, const QString &redirectUri) + : QObject(nullptr), mWebView(nullptr), mWebProfile(), mWebPage(&mWebProfile), mReplyHandler(this, redirectUri), + mRequestInterceptor(this, redirectUri), mEmail(email), mRedirectUri(redirectUri), mState(EwsOAuth::NotAuthenticated), + mParentWindow(nullptr), q_ptr(parent) +{ + mOAuth2.setReplyHandler(&mReplyHandler); + mOAuth2.setAuthorizationUrl(o365AuthorizationUrl); + mOAuth2.setAccessTokenUrl(o365AccessTokenUrl); + mOAuth2.setClientIdentifier(appId); + + /* Bad bad Microsoft... + * When Conditional Access is enabled on the server the OAuth2 authentication server only supports Windows, + * MacOSX, Android and iOS. No option to include Linux. Support (i.e. guarantee that it works) + * is one thing, but blocking unsupported browsers completely is just wrong. + * Fortunately enough this can be worked around by faking the user agent to something "supported". + */ + mWebProfile.setHttpUserAgent(o365FakeUserAgent); + + mWebProfile.setRequestInterceptor(&mRequestInterceptor); + mWebProfile.installUrlSchemeHandler("urn", &mSchemeHandler); + + mWebView.setPage(&mWebPage); + + mOAuth2.setModifyParametersFunction([&](QAbstractOAuth::Stage stage, QVariantMap *parameters) { + modifyParametersFunction(stage, parameters); + }); + connect(&mOAuth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, this, &EwsOAuthPrivate::authorizeWithBrowser); + connect(&mOAuth2, &QOAuth2AuthorizationCodeFlow::granted, this, &EwsOAuthPrivate::granted); + connect(&mOAuth2, &QOAuth2AuthorizationCodeFlow::error, this, &EwsOAuthPrivate::error); + connect(&mRequestInterceptor, &EwsOAuthRequestInterceptor::redirectUriIntercepted, this, + &EwsOAuthPrivate::redirectUriIntercepted, Qt::QueuedConnection); +} + +void EwsOAuthPrivate::authenticate() +{ + qCInfoNC(EWSCLI_LOG) << QStringLiteral("Starting OAuth2 authentication"); + + mState = EwsOAuth::Authenticating; + + mOAuth2.grant(); +} + +void EwsOAuthPrivate::modifyParametersFunction(QAbstractOAuth::Stage stage, QVariantMap *parameters) +{ + switch (stage) { + case QAbstractOAuth::Stage::RequestingAccessToken: + parameters->insert(QStringLiteral("resource"), o365Resource); + break; + case QAbstractOAuth::Stage::RequestingAuthorization: + parameters->insert(QStringLiteral("prompt"), QStringLiteral("login")); + parameters->insert(QStringLiteral("login_hint"), mEmail); + parameters->insert(QStringLiteral("resource"), o365Resource); + break; + default: + break; + } +} + +void EwsOAuthPrivate::authorizeWithBrowser(const QUrl &url) +{ + qCInfoNC(EWSCLI_LOG) << QStringLiteral("Launching browser for authentication"); + + mWebDialog = new QDialog(nullptr); + mWebDialog->setObjectName(QStringLiteral("Akonadi EWS Resource - Authentication")); + mWebDialog->setWindowIcon(QIcon("akonadi-ews")); + mWebDialog->resize(400, 500); + auto layout = new QHBoxLayout(mWebDialog); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(&mWebView); + mWebView.show(); + + mWebView.load(url); + mWebDialog->show(); +} + +void EwsOAuthPrivate::redirectUriIntercepted(const QUrl &url) +{ + qCDebug(EWSCLI_LOG) << QStringLiteral("Intercepted redirect URI from browser"); + + QUrlQuery query(url); + QVariantMap varmap; + for (const auto item : query.queryItems()) { + varmap[item.first] = item.second; + } + mOAuth2.authorizationCallbackReceived(varmap); + mWebView.stop(); + mWebDialog->hide(); +} + +void EwsOAuthPrivate::granted() +{ + Q_Q(EwsOAuth); + + mState = EwsOAuth::Authenticated; + + // TODO: Store refreshUri + + qCInfo(EWSCLI_LOG) << QStringLiteral("Authentication succeeded"); + + Q_EMIT(q->granted()); +} + +void EwsOAuthPrivate::error(const QString &error, const QString &errorDescription, const QUrl &uri) +{ + Q_Q(EwsOAuth); + + mState = EwsOAuth::AuthenticationFailed; + + qCInfoNC(EWSCLI_LOG) << QStringLiteral("Authentication failed: ") << error << errorDescription; + + Q_EMIT(q->error(error, errorDescription, uri)); +} + +EwsOAuth::EwsOAuth(QObject *parent, const QString &email, const QString &appId, const QString &redirectUri) + : QObject(parent), d_ptr(new EwsOAuthPrivate(this, email, appId, redirectUri)) +{ +} + +EwsOAuth::~EwsOAuth() +{ +} + +void EwsOAuth::authenticate() +{ + Q_D(EwsOAuth); + + d->authenticate(); +} + +QString EwsOAuth::token() const +{ + Q_D(const EwsOAuth); + + return d->mOAuth2.token(); +} + +EwsOAuth::State EwsOAuth::state() const +{ + Q_D(const EwsOAuth); + + return d->mState; +} + +#include "ewsoauth.moc" diff --git a/resources/ews/ewsclient/ewsoauth.h b/resources/ews/ewsclient/ewsoauth.h new file mode 100644 index 000000000..7da8d3f6e --- /dev/null +++ b/resources/ews/ewsclient/ewsoauth.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2018 Krzysztof Nowicki + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef EWSOAUTH_H +#define EWSOAUTH_H + +#include +#include + +class EwsOAuthPrivate; + +class EwsOAuth : public QObject +{ + Q_OBJECT +public: + enum State { + NotAuthenticated, + Authenticating, + Authenticated, + AuthenticationFailed + }; + + EwsOAuth(QObject *parent, const QString &email, const QString &appId, const QString &redirectUri); + ~EwsOAuth() override; + + void authenticate(); + QString token() const; + State state() const; +Q_SIGNALS: + void granted(); + void error(const QString &error, const QString &errorDescription, const QUrl &uri); +private: + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(EwsOAuth) +}; + +#endif /* EWSOAUTH_H */ diff --git a/resources/ews/ewsresource.kcfg b/resources/ews/ewsresource.kcfg index c24da0a04..35e52f354 100644 --- a/resources/ews/ewsresource.kcfg +++ b/resources/ews/ewsresource.kcfg @@ -1,65 +1,76 @@ The URL of the Microsoft Exchange server, should be something like https://myserver.org/EWS/Exchange.asmx The URL of the Microsoft Exchange server, should be something like https://myserver.org/EWS/Exchange.asmx The username that is used to log into the Microsoft Exchange server The username that is used to log into the Microsoft Exchange server The Active Directory domain the user belongs to The Active Directory domain the user belongs to true The primary e-mail address of this account The primary e-mail address of this account Attempt to automatically discover Exchange server address Attempts to find out the Microsoft Exchange server address relevant to the supplied e-mail address. Sets the interval for checking for new mail Sets the interval for checking for new mail. default true + + username-password + + + + d3590ed6-52b3-4102-aeff-aad2292ab01c + + + + urn:ietf:wg:oauth:2.0:oob +