File indexing completed on 2023-11-26 08:17:52

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