File indexing completed on 2024-05-05 05:02:17

0001 /*
0002    SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "rocketchataccountsettings.h"
0008 #include "config-ruqola.h"
0009 #include "localdatabase/localdatabaseutils.h"
0010 #include "managerdatapaths.h"
0011 #include "ruqola_debug.h"
0012 #include "ruqola_password_core_debug.h"
0013 
0014 #include <QDateTime>
0015 #include <QDir>
0016 #include <QFile>
0017 #include <QSettings>
0018 #include <QStandardPaths>
0019 #include <qt6keychain/keychain.h>
0020 using namespace QKeychain;
0021 
0022 RocketChatAccountSettings::RocketChatAccountSettings(const QString &accountFileName, QObject *parent)
0023     : QObject(parent)
0024 {
0025     initializeSettings(accountFileName);
0026 }
0027 
0028 RocketChatAccountSettings::~RocketChatAccountSettings()
0029 {
0030     mSetting->sync();
0031     delete mSetting;
0032 }
0033 
0034 bool RocketChatAccountSettings::isValid() const
0035 {
0036     return !mServerUrl.isEmpty() && !mUserName.isEmpty();
0037 }
0038 
0039 void RocketChatAccountSettings::initializeSettings(const QString &accountFileName)
0040 {
0041     delete mSetting;
0042     mSetting = new QSettings(accountFileName, QSettings::IniFormat);
0043     qCDebug(RUQOLA_LOG) << "accountFileName " << accountFileName;
0044 
0045     mServerUrl = mSetting->value(QStringLiteral("serverURL"), QStringLiteral("open.rocket.chat")).toString();
0046     mUserName = mSetting->value(QStringLiteral("username")).toString();
0047     mUserId = mSetting->value(QStringLiteral("userID")).toString();
0048     mAuthToken = mSetting->value(QStringLiteral("authToken")).toString();
0049     mExpireToken = mSetting->value(QStringLiteral("expireToken")).toLongLong();
0050     mAccountName = mSetting->value(QStringLiteral("accountName")).toString();
0051     mUseLdap = mSetting->value(QStringLiteral("useLdap")).toBool();
0052     mAccountEnabled = mSetting->value(QStringLiteral("enabled"), true).toBool();
0053     mDisplayName = mSetting->value(QStringLiteral("displayName")).toString();
0054     mLastCheckedPreviewUrlCacheDate = mSetting->value(QStringLiteral("lastCheckedPreviewUrlDate")).toDate();
0055 
0056     if (mAccountEnabled && !mAccountName.isEmpty()) {
0057         qCDebug(RUQOLA_PASSWORD_CORE_LOG) << "Load password from QKeychain: accountname " << mAccountName;
0058         auto readJob = new ReadPasswordJob(QStringLiteral("Ruqola"), this);
0059         connect(readJob, &Job::finished, this, &RocketChatAccountSettings::slotPasswordRead);
0060         readJob->setKey(mAccountName);
0061         readJob->start();
0062     }
0063 }
0064 
0065 void RocketChatAccountSettings::slotPasswordRead(QKeychain::Job *baseJob)
0066 {
0067     auto job = qobject_cast<ReadPasswordJob *>(baseJob);
0068     Q_ASSERT(job);
0069     if (!job->error()) {
0070         mPassword = job->textData();
0071         qCDebug(RUQOLA_PASSWORD_CORE_LOG) << "OK, we have the password now";
0072         Q_EMIT passwordChanged();
0073     } else {
0074         qCWarning(RUQOLA_PASSWORD_CORE_LOG) << "We have an error during reading password " << job->errorString() << " Account name " << mAccountName;
0075     }
0076 }
0077 
0078 void RocketChatAccountSettings::slotPasswordWritten(QKeychain::Job *baseJob)
0079 {
0080     if (baseJob->error()) {
0081         qCWarning(RUQOLA_PASSWORD_CORE_LOG) << "Error writing password using QKeychain:" << baseJob->errorString();
0082     }
0083 }
0084 
0085 QDate RocketChatAccountSettings::lastCheckedPreviewUrlCacheDate() const
0086 {
0087     return mLastCheckedPreviewUrlCacheDate;
0088 }
0089 
0090 void RocketChatAccountSettings::setLastCheckedPreviewUrlCacheDate(const QDate &newLastCheckedPreviewUrlCacheDate)
0091 {
0092     if (mLastCheckedPreviewUrlCacheDate != newLastCheckedPreviewUrlCacheDate) {
0093         mLastCheckedPreviewUrlCacheDate = newLastCheckedPreviewUrlCacheDate;
0094         mSetting->setValue(QStringLiteral("lastCheckedPreviewUrlDate"), mLastCheckedPreviewUrlCacheDate);
0095         mSetting->sync();
0096     }
0097 }
0098 
0099 QString RocketChatAccountSettings::displayName() const
0100 {
0101     if (mDisplayName.isEmpty()) {
0102         return mAccountName;
0103     }
0104     return mDisplayName;
0105 }
0106 
0107 void RocketChatAccountSettings::setDisplayName(const QString &displayName)
0108 {
0109     if (mDisplayName != displayName) {
0110         mDisplayName = displayName;
0111         mSetting->setValue(QStringLiteral("displayName"), mDisplayName);
0112         mSetting->sync();
0113         Q_EMIT displayNameChanged();
0114     }
0115 }
0116 
0117 bool RocketChatAccountSettings::accountEnabled() const
0118 {
0119     return mAccountEnabled;
0120 }
0121 
0122 void RocketChatAccountSettings::setAccountEnabled(bool enabled)
0123 {
0124     if (mAccountEnabled != enabled) {
0125         mAccountEnabled = enabled;
0126         mSetting->setValue(QStringLiteral("enabled"), mAccountEnabled);
0127         mSetting->sync();
0128         Q_EMIT enableAccountChanged();
0129     }
0130 }
0131 
0132 QString RocketChatAccountSettings::lastSelectedRoom() const
0133 {
0134     return mSetting->value(QStringLiteral("SelectedRoom")).toString();
0135 }
0136 
0137 void RocketChatAccountSettings::setLastSelectedRoom(const QString &roomId)
0138 {
0139     if (!roomId.isEmpty()) {
0140         mSetting->setValue(QStringLiteral("SelectedRoom"), roomId);
0141     }
0142 }
0143 
0144 qint64 RocketChatAccountSettings::expireToken() const
0145 {
0146     return mExpireToken;
0147 }
0148 
0149 void RocketChatAccountSettings::setExpireToken(qint64 expireToken)
0150 {
0151     if (mExpireToken != expireToken) {
0152         mExpireToken = expireToken;
0153         mSetting->setValue(QStringLiteral("expireToken"), mExpireToken);
0154         mSetting->sync();
0155     }
0156 }
0157 
0158 bool RocketChatAccountSettings::tokenExpired() const
0159 {
0160     return mExpireToken < QDateTime::currentDateTime().toMSecsSinceEpoch();
0161 }
0162 
0163 QString RocketChatAccountSettings::userId() const
0164 {
0165     return mUserId;
0166 }
0167 
0168 void RocketChatAccountSettings::setUserId(const QString &userId)
0169 {
0170     // Don't use if( m_userID != userID) as we need to Q_EMIT userIDChanged
0171     mUserId = userId;
0172     mSetting->setValue(QStringLiteral("userID"), userId);
0173     mSetting->sync();
0174     Q_EMIT userIdChanged();
0175 }
0176 
0177 QString RocketChatAccountSettings::authToken() const
0178 {
0179     return mAuthToken;
0180 }
0181 
0182 void RocketChatAccountSettings::setAuthToken(const QString &authToken)
0183 {
0184     if (mAuthToken != authToken) {
0185         qCDebug(RUQOLA_LOG) << "Setting token to" << authToken;
0186         mAuthToken = authToken;
0187         mSetting->setValue(QStringLiteral("authToken"), authToken);
0188     }
0189 }
0190 
0191 void RocketChatAccountSettings::logout()
0192 {
0193     mSetting->setValue(QStringLiteral("authToken"), QString());
0194     mSetting->setValue(QStringLiteral("expireToken"), -1);
0195     mSetting->sync();
0196     mAuthToken.clear();
0197     mUserId.clear();
0198     mExpireToken = -1;
0199 }
0200 
0201 QString RocketChatAccountSettings::password() const
0202 {
0203     return mPassword;
0204 }
0205 
0206 void RocketChatAccountSettings::setPassword(const QString &password)
0207 {
0208     mPassword = password;
0209 
0210     auto writeJob = new WritePasswordJob(QStringLiteral("Ruqola"), this);
0211     connect(writeJob, &Job::finished, this, &RocketChatAccountSettings::slotPasswordWritten);
0212     writeJob->setKey(mAccountName);
0213     writeJob->setTextData(mPassword);
0214     writeJob->start();
0215 
0216     Q_EMIT passwordChanged();
0217 }
0218 
0219 QString RocketChatAccountSettings::twoFactorAuthenticationCode() const
0220 {
0221     return mTwoFactorAuthenticationCode;
0222 }
0223 
0224 void RocketChatAccountSettings::setTwoFactorAuthenticationCode(const QString &twoFactorAuthenticationCode)
0225 {
0226     if (mTwoFactorAuthenticationCode != twoFactorAuthenticationCode) {
0227         mTwoFactorAuthenticationCode = twoFactorAuthenticationCode;
0228 
0229         Q_EMIT twoFactorAuthenticationCodeChanged();
0230     }
0231 }
0232 
0233 QString RocketChatAccountSettings::userName() const
0234 {
0235     return mUserName;
0236 }
0237 
0238 void RocketChatAccountSettings::setUserName(const QString &userName)
0239 {
0240     if (mUserName != userName) {
0241         mUserName = userName;
0242         mSetting->setValue(QStringLiteral("username"), mUserName);
0243         mSetting->sync();
0244         Q_EMIT userNameChanged();
0245     }
0246 }
0247 
0248 QString RocketChatAccountSettings::accountName() const
0249 {
0250     return mAccountName;
0251 }
0252 
0253 void RocketChatAccountSettings::setAccountName(const QString &accountName)
0254 {
0255     if (mAccountName == accountName) {
0256         return;
0257     }
0258 
0259     initializeSettings(ManagerDataPaths::self()->accountConfigFileName(accountName));
0260     mSetting->setValue(QStringLiteral("accountName"), accountName);
0261     mSetting->sync();
0262     mAccountName = accountName;
0263     Q_EMIT accountNameChanged();
0264 }
0265 
0266 QString RocketChatAccountSettings::serverUrl() const
0267 {
0268     return mServerUrl;
0269 }
0270 
0271 void RocketChatAccountSettings::setServerUrl(const QString &serverUrl)
0272 {
0273     if (mServerUrl == serverUrl) {
0274         return;
0275     }
0276 
0277     mSetting->setValue(QStringLiteral("serverURL"), serverUrl);
0278     mSetting->sync();
0279     mServerUrl = serverUrl;
0280     Q_EMIT serverURLChanged();
0281 }
0282 
0283 QString RocketChatAccountSettings::cacheBasePath()
0284 {
0285     if (mServerUrl.isEmpty()) {
0286         return {};
0287     }
0288     if (mCachePath.isEmpty()) {
0289         mCachePath = ManagerDataPaths::self()->path(ManagerDataPaths::Cache, mAccountName);
0290         QDir dir;
0291         if (!dir.mkpath(mCachePath)) {
0292             qCWarning(RUQOLA_LOG) << "Impossible to create cache directory" << mCachePath;
0293         }
0294     }
0295     return mCachePath;
0296 }
0297 
0298 void RocketChatAccountSettings::removeSettings()
0299 {
0300     // Delete password
0301     auto deleteJob = new DeletePasswordJob(QStringLiteral("Ruqola"));
0302     deleteJob->setKey(mAccountName);
0303     deleteJob->start();
0304     QFile f(mSetting->fileName());
0305     if (!f.remove()) {
0306         qCWarning(RUQOLA_LOG) << "Impossible to delete config file: " << mSetting->fileName();
0307     }
0308 
0309     const QString storeCachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + mAccountName + QLatin1Char('/');
0310     QDir dir(storeCachePath);
0311     if (!dir.removeRecursively()) {
0312         qCWarning(RUQOLA_LOG) << "Impossible to delete cache dir: " << storeCachePath;
0313     }
0314 }
0315 
0316 #include "moc_rocketchataccountsettings.cpp"