MuseScore/mscore/loginmanager.cpp
2014-11-24 17:30:07 +01:00

446 lines
19 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2014 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "loginmanager.h"
#include "musescore.h"
#include "kQOAuth/kqoauthrequest.h"
#include "kQOAuth/kqoauthrequest_xauth.h"
namespace Ms {
extern QString dataPath;
//---------------------------------------------------------
// LoginManager
//---------------------------------------------------------
LoginManager::LoginManager(QObject* parent)
: QObject(parent)
{
_oauthManager = new KQOAuthManager(this);
connect(_oauthManager, SIGNAL(accessTokenReceived(QString, QString)),
this, SLOT(onAccessTokenReceived(QString, QString)));
connect(_oauthManager, SIGNAL(authorizedRequestDone()),
this, SLOT(onAuthorizedRequestDone()));
QByteArray ba;
ba.resize(32);
ba[0] = 0x52; ba[1] = 0x61; ba[2] = 0x70; ba[3] = 0x33;
ba[4] = 0x74; ba[5] = 0x52; ba[6] = 0x58; ba[7] = 0x70;
ba[8] = 0x62; ba[9] = 0x43; ba[10] = 0x70; ba[11] = 0x39;
ba[12] = 0x36; ba[13] = 0x35; ba[14] = 0x46; ba[15] = 0x4a;
ba[16] = 0x64; ba[17] = 0x5a; ba[18] = 0x46; ba[19] = 0x75;
ba[20] = 0x54; ba[21] = 0x35; ba[22] = 0x5a; ba[23] = 0x63;
ba[24] = 0x42; ba[25] = 0x73; ba[26] = 0x4b; ba[27] = 0x67;
ba[28] = 0x4a; ba[29] = 0x7a; ba[30] = 0x4c; ba[31] = 0x44;
_consumerKey = QString(ba);
ba[0] = 0x35; ba[1] = 0x39; ba[2] = 0x33; ba[3] = 0x61;
ba[4] = 0x57; ba[5] = 0x6f; ba[6] = 0x51; ba[7] = 0x73;
ba[8] = 0x77; ba[9] = 0x73; ba[10] = 0x50; ba[11] = 0x44;
ba[12] = 0x56; ba[13] = 0x48; ba[14] = 0x37; ba[15] = 0x4c;
ba[16] = 0x58; ba[17] = 0x76; ba[18] = 0x6e; ba[19] = 0x61;
ba[20] = 0x51; ba[21] = 0x71; ba[22] = 0x34; ba[23] = 0x4b;
ba[24] = 0x45; ba[25] = 0x5a; ba[26] = 0x42; ba[27] = 0x4a;
ba[28] = 0x64; ba[29] = 0x74; ba[30] = 0x4e; ba[31] = 0x74;
_consumerSecret = QString(ba);
load();
}
//---------------------------------------------------------
// save
//---------------------------------------------------------
bool LoginManager::save()
{
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty())
return true;
QFile saveFile(dataPath + "/cred.dat");
if (!saveFile.open(QIODevice::WriteOnly))
return false;
QJsonObject saveObject;
saveObject["accessToken"] = _accessToken;
saveObject["accessTokenSecret"] = _accessTokenSecret;
QJsonDocument saveDoc(saveObject);
saveFile.write(saveDoc.toBinaryData());
saveFile.close();
return true;
}
//---------------------------------------------------------
// load
//---------------------------------------------------------
bool LoginManager::load()
{
QFile loadFile(dataPath + "/cred.dat");
if (!loadFile.open(QIODevice::ReadOnly))
return false;
QByteArray saveData = loadFile.readAll();
QJsonDocument loadDoc(QJsonDocument::fromBinaryData(saveData));
QJsonObject saveObject = loadDoc.object();
_accessToken = saveObject["accessToken"].toString();
_accessTokenSecret = saveObject["accessTokenSecret"].toString();
loadFile.close();
return true;
}
//---------------------------------------------------------
// onAuthorizedRequestDone
//---------------------------------------------------------
void LoginManager::onAuthorizedRequestDone()
{
if (_oauthManager->lastError() == KQOAuthManager::NetworkError)
QMessageBox::critical(0, tr("Network error"), tr("Please check your internet connection"));
else if (_oauthManager->lastError() == KQOAuthManager::ContentOperationNotPermittedError)
QMessageBox::critical(0, tr("Please upgrade"), tr("Your MuseScore version is too old to use this feature.<br/> <a href=\"%1\">Please upgrade first</a>.").arg("http://musescore.org"));
}
/*------- TRY LOGIN ROUTINES ----------------------------*/
/* Try to get user information, if error, */
/* display login form until quit or successful login */
//---------------------------------------------------------
// tryLogin
//---------------------------------------------------------
void LoginManager::tryLogin()
{
disconnect(this, SIGNAL(loginSuccess()), this, SLOT(tryLogin()));
connect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
connect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
getUser();
}
//---------------------------------------------------------
// onTryLoginSuccess
//---------------------------------------------------------
void LoginManager::onTryLoginSuccess()
{
disconnect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
disconnect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
emit tryLoginSuccess();
}
//---------------------------------------------------------
// onTryLoginError
//---------------------------------------------------------
void LoginManager::onTryLoginError(const QString& error)
{
Q_UNUSED(error);
disconnect(this, SIGNAL(getUserSuccess()), this, SLOT(onTryLoginSuccess()));
disconnect(this, SIGNAL(getUserError(QString)), this, SLOT(onTryLoginError(QString)));
connect(this, SIGNAL(loginSuccess()), this, SLOT(tryLogin()));
mscore->showLoginDialog();
}
/*------- END - TRY LOGIN ROUTINES ----------------------------*/
//---------------------------------------------------------
// login
//---------------------------------------------------------
void LoginManager::login(QString login, QString password)
{
if(login == "" || password == "")
return;
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onAccessTokenRequestReady(QByteArray)), Qt::UniqueConnection);
KQOAuthRequest_XAuth *oauthRequest = new KQOAuthRequest_XAuth(this);
oauthRequest->initRequest(KQOAuthRequest::AccessToken, QUrl("https://api.musescore.com/oauth/access_token"));
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setXAuthLogin(login, password);
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onAccessTokenReceived
//---------------------------------------------------------
void LoginManager::onAccessTokenReceived(QString token, QString tokenSecret)
{
//qDebug() << "Access token received: " << token << tokenSecret;
_accessToken = token;
_accessTokenSecret = tokenSecret;
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)), this, SLOT(onAccessTokenRequestReady(QByteArray)));
emit loginSuccess();
}
//---------------------------------------------------------
// onAccessTokenRequestReady
//---------------------------------------------------------
void LoginManager::onAccessTokenRequestReady(QByteArray ba)
{
//qDebug() << "onAccessTokenRequestReady" << ba;
if (_oauthManager->lastError() == KQOAuthManager::RequestUnauthorized) { // 401/406
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonArray array = jsonResponse.array();
QString message = tr("Unsuccessful login. Please try again.");
if (array.size() > 0) {
QJsonObject o = array.at(0).toObject();
if (o.value("code") != QJsonValue::Undefined) {
QString code = o["code"].toString();
if (code == "USER_AUTHENTICATION_FAILED") {
message = tr("Sorry, wrong email address, username or password. Please check again. <a href=\"%1\">Have you forgotten your password</a>?").arg("https://musescore.com/user/password");
}
else if (code == "USER_DENIED") {
message = tr("This account has been blocked.");
}
else if (code == "USER_NOT_ACTIVATED") {
message = tr("Your account has not been activated yet. Please check your mailbox to activate your account or <a href=\"%1\">request a new activation email</a>.").arg("https://musescore.com/user/resendregistrationpassword");
}
}
}
emit loginError(message);
}
else if (_oauthManager->lastError() == KQOAuthManager::NetworkError) {
QMessageBox::critical(0, tr("Network error"), tr("Please check your internet connection"));
}
else if (_oauthManager->lastError() == KQOAuthManager::ContentOperationNotPermittedError) {
QMessageBox::critical(0, tr("Please upgrade"), tr("Your MuseScore version is too old to use this feature.<br/> <a href=\"%1\">Please upgrade first</a>.").arg("http://musescore.org"));
}
}
//---------------------------------------------------------
// getUser
//---------------------------------------------------------
void LoginManager::getUser()
{
//qDebug() << "getUser";
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty()) {
emit getUserError("getUser - No token");
return;
}
KQOAuthRequest * oauthRequest = new KQOAuthRequest();
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, QUrl("https://api.musescore.com/services/rest/me.json"));
oauthRequest->setHttpMethod(KQOAuthRequest::GET);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetUserRequestReady(QByteArray)));
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onGetUserRequestReady
//---------------------------------------------------------
void LoginManager::onGetUserRequestReady(QByteArray ba)
{
//qDebug() << "onGetUserRequestReady" << ba;
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetUserRequestReady(QByteArray)));
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject user = jsonResponse.object();
if (user.value("name") != QJsonValue::Undefined) {
_userName = user.value("name").toString();
_uid = user.value("id").toString().toInt();
emit getUserSuccess();
}
else {
emit getUserError(tr("Error while getting user info. Please try again"));
}
}
else if (_oauthManager->lastError() != KQOAuthManager::NetworkError) {
emit getUserError(tr("Error while getting user info: %1").arg(_oauthManager->lastError()));
}
}
//---------------------------------------------------------
// getScore
//---------------------------------------------------------
void LoginManager::getScore(int nid)
{
//qDebug() << "getScore";
if (_accessToken.isEmpty() || _accessTokenSecret.isEmpty()) {
emit getScoreError("getScore - No token");
return;
}
KQOAuthRequest * oauthRequest = new KQOAuthRequest();
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, QUrl(QString("https://api.musescore.com/services/rest/score/%1.json").arg(nid)));
oauthRequest->setHttpMethod(KQOAuthRequest::GET);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetScoreRequestReady(QByteArray)));
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onGetUserRequestReady
//---------------------------------------------------------
void LoginManager::onGetScoreRequestReady(QByteArray ba)
{
//qDebug() << "onGetScoreRequestReady" << ba;
//qDebug() << _oauthManager->lastError();
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onGetScoreRequestReady(QByteArray)));
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject score = jsonResponse.object();
if (score.value("user") != QJsonValue::Undefined) {
QJsonObject user = score.value("user").toObject();
QString title = score.value("title").toString();
QString description = score.value("description").toString();
QString sharing = score.value("sharing").toString();
QString license = score.value("license").toString();
QString tags = score.value("tags").toString();
if (user.value("uid") != QJsonValue::Undefined) {
int uid = user.value("uid").toString().toInt();
if (uid == _uid)
emit getScoreSuccess(title, description, (sharing == "private"), license, tags);
else
emit getScoreError("");
}
else {
emit getScoreError("");
}
}
else {
emit getScoreError("");
}
}
else {
emit getScoreError("");
}
}
//---------------------------------------------------------
// upload
//---------------------------------------------------------
void LoginManager::upload(const QString &path, int nid, const QString &title, const QString &description, const QString& priv, const QString& license, const QString& tags)
{
//qDebug() << "file upload";
KQOAuthRequest *oauthRequest = new KQOAuthRequest(this);
QUrl url("https://api.musescore.com/services/rest/score.json");
if (nid > 0)
url = QUrl(QString("https://api.musescore.com/services/rest/score/%1/update.json").arg(nid));
oauthRequest->initRequest(KQOAuthRequest::AuthorizedRequest, url);
oauthRequest->setConsumerKey(_consumerKey);
oauthRequest->setConsumerSecretKey(_consumerSecret);
oauthRequest->setToken(_accessToken);
oauthRequest->setTokenSecret(_accessTokenSecret);
oauthRequest->setContentType("multipart/form-data");
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"score_data\"; filename=\"temp.mscz\""));
QFile *file = new QFile(path);
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(filePart);
QHttpPart titlePart;
titlePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"title\""));
titlePart.setBody(title.toUtf8());
multiPart->append(titlePart);
QHttpPart descriptionPart;
descriptionPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"description\""));
descriptionPart.setBody(description.toUtf8());
multiPart->append(descriptionPart);
QHttpPart privatePart;
privatePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"private\""));
privatePart.setBody(priv.toUtf8());
multiPart->append(privatePart);
QHttpPart licensePart;
licensePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"license\""));
licensePart.setBody(license.toUtf8());
multiPart->append(licensePart);
QHttpPart tagsPart;
tagsPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"tags\""));
tagsPart.setBody(tags.toUtf8());
multiPart->append(tagsPart);
connect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onUploadRequestReady(QByteArray)));
oauthRequest->setHttpMultiPart(multiPart);
_oauthManager->executeRequest(oauthRequest);
}
//---------------------------------------------------------
// onUploadRequestReady
//---------------------------------------------------------
void LoginManager::onUploadRequestReady(QByteArray ba)
{
disconnect(_oauthManager, SIGNAL(requestReady(QByteArray)),
this, SLOT(onUploadRequestReady(QByteArray)));
//qDebug() << "onUploadRequestReady" << ba;
if (_oauthManager->lastError() == KQOAuthManager::NoError) {
QJsonDocument jsonResponse = QJsonDocument::fromJson(ba);
QJsonObject score = jsonResponse.object();
if (score.value("permalink") != QJsonValue::Undefined) {
emit uploadSuccess(score.value("permalink").toString());
}
else {
emit uploadError(tr("An error occurred during the file transfer. Please try again"));
}
}
else {
emit uploadError(tr("Cannot upload: %1").arg(_oauthManager->lastError()));
}
}
//---------------------------------------------------------
// hasAccessToken
//---------------------------------------------------------
bool LoginManager::hasAccessToken()
{
return !_accessTokenSecret.isEmpty() && !_accessToken.isEmpty();
}
//---------------------------------------------------------
// logout
//---------------------------------------------------------
bool LoginManager::logout()
{
_accessToken = "";
_accessTokenSecret = "";
QFile loadFile(dataPath + "/cred.dat");
if (!loadFile.exists())
return true;
return loadFile.remove();
}
}