From 0f8b62b182c30ad9009b5148ddae21abc792bb70 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshnikov Date: Tue, 15 Jan 2019 23:19:19 +0300 Subject: [PATCH] Add enterprise license check --- src/core/core.cpp | 34 ++++++++++ src/core/core.h | 3 + src/core/request.cpp | 4 +- src/framework/access/access.cpp | 101 ++++++++++++++++++++++------ src/framework/access/access.h | 2 + src/framework/access/signdialog.cpp | 18 ++++- 6 files changed, 140 insertions(+), 22 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 4dc9713..c79e879 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -21,7 +21,41 @@ #include "core/version.h" +#include "cpl_json.h" + const char* getVersion() { return NGLIB_VERSION_STRING; } + +QMap jsonToMap(const QString &path) +{ + QMap out; + CPLJSONDocument in; + if(in.Load(path.toStdString())) { + CPLJSONObject root = in.GetRoot(); + for(const CPLJSONObject &child : root.GetChildren()) { + QString name = QString::fromStdString(child.GetName()); + switch(child.GetType()) { + case CPLJSONObject::Boolean: + out[name] = child.ToBool(); + break; + case CPLJSONObject::String: + out[name] = QString::fromStdString(child.ToString()); + break; + case CPLJSONObject::Integer: + out[name] = child.ToInteger(); + break; + case CPLJSONObject::Long: + out[name] = child.ToLong(); + break; + case CPLJSONObject::Double: + out[name] = child.ToDouble(); + break; + default: + out[name] = QString::fromStdString(child.ToString()); + } + } + } + return out; +} diff --git a/src/core/core.h b/src/core/core.h index c135878..4002fff 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -22,6 +22,8 @@ #include +#include + #if defined(NGSTD_CORE_LIBRARY) # define NGCORE_EXPORT Q_DECL_EXPORT #else @@ -34,5 +36,6 @@ NGCORE_EXPORT const char *getVersion(); +NGCORE_EXPORT QMap jsonToMap(const QString &path); #endif // NGSTD_CORE_H diff --git a/src/core/request.cpp b/src/core/request.cpp index b94177c..7d7ab50 100644 --- a/src/core/request.cpp +++ b/src/core/request.cpp @@ -288,7 +288,7 @@ QMap NGRequest::getJsonAsMap(const QString &url) out[name] = child.ToBool(); break; case CPLJSONObject::String: - out[name] = QString::fromUtf8(child.ToString().c_str()); + out[name] = QString::fromStdString(child.ToString()); break; case CPLJSONObject::Integer: out[name] = child.ToInteger(); @@ -300,7 +300,7 @@ QMap NGRequest::getJsonAsMap(const QString &url) out[name] = child.ToDouble(); break; default: - out[name] = QString::fromUtf8(child.ToString().c_str()); + out[name] = QString::fromStdString(child.ToString()); } } } diff --git a/src/framework/access/access.cpp b/src/framework/access/access.cpp index e47f725..6b4f11a 100644 --- a/src/framework/access/access.cpp +++ b/src/framework/access/access.cpp @@ -106,6 +106,23 @@ NGAccess::NGAccess() : m_supported(false), m_avatar(QIcon(":/icons/person-blue.svg")) { + // Setup license key file + QFileInfo appDir(QCoreApplication::applicationDirPath()); + +#if defined Q_OS_WIN + m_licenseDir = appDir.dir().absoluteFilePath("share\\license"); +#elif defined(Q_OS_MACX) + // 4 level up + QDir updaterDir = appDir.dir(); + updaterDir.cdUp(); + updaterDir.cdUp(); + updaterDir.cdUp(); + m_licenseDir = updaterDir.absoluteFilePath("usr/share/license"); +#else + m_licenseDir = QLatin1String("/usr/share/license"); +#endif + + m_updateUserInfoWatcher = new QFutureWatcher(this); connect(m_updateUserInfoWatcher, SIGNAL(finished()), this, SLOT(onUserInfoUpdated())); @@ -207,6 +224,10 @@ void NGAccess::setClientId(const QString &clientId) updateUserInfo(); updateSupportInfo(); } + else if(isEnterprise()) { + updateUserInfo(); + updateSupportInfo(); + } else { m_avatar = QIcon(":/icons/person-blue.svg"); } @@ -273,6 +294,12 @@ bool NGAccess::isUserAuthorized() const return m_authorized; } +bool NGAccess::isEnterprise() const +{ + QFileInfo licenseJson(QDir(m_licenseDir).filePath("license.json")); + return licenseJson.exists() && licenseJson.isFile(); +} + bool NGAccess::checkSupported() { // Read user id, start/end dates, account type @@ -413,13 +440,24 @@ void NGAccess::getTokens(const QString &code, const QString &redirectUri) } } -extern void updateUserInfoFunction(const QString &configDir) +extern void updateUserInfoFunction(const QString &configDir, const QString &licenseDir) { - auto result = NGRequest::getJsonAsMap(QString("%1/user_info/").arg(apiEndpoint)); - QString firstName = result["first_name"].toString(); - QString lastName = result["last_name"].toString(); - QString email = result["email"].toString(); - QString userId = result["nextgis_guid"].toString(); + QString firstName, lastName, email, userId; + + // Check local files before request my.nextgis.com + QFileInfo licenseJson(QDir(licenseDir).filePath("license.json")); + QMap result; + if(licenseJson.exists() && licenseJson.isFile()) { + result = jsonToMap(licenseJson.absoluteFilePath()); + } + else { + result = NGRequest::getJsonAsMap(QString("%1/user_info/").arg(apiEndpoint)); + + } + firstName = result["first_name"].toString(); + lastName = result["last_name"].toString(); + email = result["email"].toString(); + userId = result["nextgis_guid"].toString(); QString settingsFilePath = configDir + QDir::separator() + QLatin1String(settingsFile); QSettings settings(settingsFilePath, QSettings::IniFormat); @@ -429,27 +467,50 @@ extern void updateUserInfoFunction(const QString &configDir) settings.setValue("last_name", lastName); // Get avatar - QString emailHash = QString(QCryptographicHash::hash( - email.toLower().toLatin1(), - QCryptographicHash::Md5).toHex()); QString avatarPath = configDir + QDir::separator() + QLatin1String(avatarFile); - NGRequest::getFile(QString("https://www.gravatar.com/avatar/%1?s=64&r=pg&d=robohash") - .arg(emailHash), avatarPath); + QFileInfo avatar(QDir(licenseDir).filePath(avatarFile)); + if(avatar.exists() && avatar.isFile()) { + if(QFile::exists(avatarPath)) { + QFile::remove(avatarPath); + } + QFile::copy(avatar.absoluteFilePath(), avatarPath); + } + else { + QString emailHash = QString(QCryptographicHash::hash( + email.toLower().toLatin1(), + QCryptographicHash::Md5).toHex()); + NGRequest::getFile(QString("https://www.gravatar.com/avatar/%1?s=64&r=pg&d=robohash") + .arg(emailHash), avatarPath); + } } -extern void updateSupportInfoFunction(const QString &configDir) +extern void updateSupportInfoFunction(const QString &configDir, const QString &licenseDir) { - auto result = NGRequest::getJsonAsMap(QString("%1/support_info/").arg(apiEndpoint)); - bool supported = result["supported"].toBool(); + bool supported = false; + QString sign, start_date, end_date; + // Check local files before request my.nextgis.com + QFileInfo licenseJson(QDir(licenseDir).filePath("license.json")); + QMap result; + if(licenseJson.exists() && licenseJson.isFile()) { + result = jsonToMap(licenseJson.absoluteFilePath()); + } + else { + result = NGRequest::getJsonAsMap(QString("%1/support_info/").arg(apiEndpoint)); + } + + supported = result["supported"].toBool(); + sign = result["sign"].toString(); + start_date = result["start_date"].toString(); + end_date = result["end_date"].toString(); QString settingsFilePath = configDir + QDir::separator() + QLatin1String(settingsFile); QSettings settings(settingsFilePath, QSettings::IniFormat); settings.setValue("supported", supported); if(supported) { - settings.setValue("sign", result["sign"].toString()); - settings.setValue("start_date", result["start_date"].toString()); - settings.setValue("end_date", result["end_date"].toString()); + settings.setValue("sign", sign); + settings.setValue("start_date", start_date); + settings.setValue("end_date", end_date); // Get key file QString keyFilePath = configDir + QDir::separator() + QLatin1String(keyFile); @@ -504,7 +565,8 @@ void NGAccess::updateUserInfo() const { auto properties = NGRequest::instance().properties(apiEndpoint); m_updateToken = properties["updateToken"]; - QFuture future = QtConcurrent::run(updateUserInfoFunction, m_configDir); + QFuture future = QtConcurrent::run(updateUserInfoFunction, m_configDir, + m_licenseDir); m_updateUserInfoWatcher->setFuture(future); } @@ -512,7 +574,8 @@ void NGAccess::updateSupportInfo() const { auto properties = NGRequest::instance().properties(apiEndpoint); m_updateToken = properties["updateToken"]; - QFuture future = QtConcurrent::run(updateSupportInfoFunction, m_configDir); + QFuture future = QtConcurrent::run(updateSupportInfoFunction, m_configDir, + m_licenseDir); m_updateSupportInfoWatcher->setFuture(future); } diff --git a/src/framework/access/access.h b/src/framework/access/access.h index f148bd7..da6acc1 100644 --- a/src/framework/access/access.h +++ b/src/framework/access/access.h @@ -41,6 +41,7 @@ class NGFRAMEWORK_EXPORT NGAccess : public QObject bool isFunctionAvailable(const QString &app, const QString &func) const; bool isUserSupported() const; bool isUserAuthorized() const; + bool isEnterprise() const; void setScope(const QString &scope); void setClientId(const QString &clientId); @@ -83,6 +84,7 @@ private slots: QString m_firstName, m_lastName; QFile m_logFile; mutable QString m_updateToken; + QString m_licenseDir; }; #endif // NGFRAMEWORK_ACCESS_H diff --git a/src/framework/access/signdialog.cpp b/src/framework/access/signdialog.cpp index 1c461f0..2f607c0 100644 --- a/src/framework/access/signdialog.cpp +++ b/src/framework/access/signdialog.cpp @@ -18,7 +18,23 @@ NGSignDialog::~NGSignDialog() void NGSignDialog::updateContent() { - if(NGAccess::instance().isUserAuthorized()) { + if(NGAccess::instance().isEnterprise()) { + ui->signButton->hide(); + ui->learnMore->hide(); + ui->userInfo->show(); + ui->userInfo->setText(QString("

%1
%2

%3

") + .arg(NGAccess::instance().firstName()) + .arg(NGAccess::instance().lastName()) + .arg(NGAccess::instance().isUserSupported() ? + tr("Supported") : tr("Unsupported"))); + ui->avatar->show(); + ui->avatar->setText(QString("

") + .arg(NGAccess::instance().avatarFilePath())); + + ui->ngLogo->hide(); + ui->descriptionText->hide(); + } + else if(NGAccess::instance().isUserAuthorized()) { // Show user info in widget // Name, big avatar, plan ui->signButton->setText(tr("Exit"));