File indexing completed on 2024-10-13 07:29:32
0001 // SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org> 0002 // SPDX-License-Identifier: GPL-2.0-or-later 0003 0004 #include "login.h" 0005 0006 #include <Quotient/accountregistry.h> 0007 #include <Quotient/connection.h> 0008 #include <Quotient/qt_connection_util.h> 0009 0010 #include "controller.h" 0011 0012 #include <KLocalizedString> 0013 0014 using namespace Quotient; 0015 0016 LoginHelper::LoginHelper(QObject *parent) 0017 : QObject(parent) 0018 { 0019 init(); 0020 } 0021 0022 void LoginHelper::init() 0023 { 0024 m_homeserverReachable = false; 0025 m_connection = new NeoChatConnection(); 0026 m_matrixId = QString(); 0027 m_password = QString(); 0028 m_deviceName = QStringLiteral("NeoChat %1 %2 %3 %4") 0029 .arg(QSysInfo::machineHostName(), QSysInfo::productType(), QSysInfo::productVersion(), QSysInfo::currentCpuArchitecture()); 0030 m_supportsSso = false; 0031 m_supportsPassword = false; 0032 m_ssoUrl = QUrl(); 0033 0034 connect(this, &LoginHelper::matrixIdChanged, this, [this]() { 0035 setHomeserverReachable(false); 0036 QRegularExpression validator(QStringLiteral("^\\@?[a-zA-Z0-9\\._=\\-/]+\\:[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)*(\\:[0-9]+)?$")); 0037 if (!validator.match(m_matrixId).hasMatch()) { 0038 return; 0039 } 0040 0041 if (m_matrixId == QLatin1Char('@')) { 0042 return; 0043 } 0044 0045 m_isLoggedIn = Controller::instance().accounts().isLoggedIn(m_matrixId); 0046 Q_EMIT isLoggedInChanged(); 0047 if (m_isLoggedIn) { 0048 return; 0049 } 0050 0051 m_testing = true; 0052 Q_EMIT testingChanged(); 0053 if (!m_connection) { 0054 m_connection = new NeoChatConnection(); 0055 } 0056 m_connection->resolveServer(m_matrixId); 0057 connectSingleShot(m_connection, &Connection::loginFlowsChanged, this, [this]() { 0058 setHomeserverReachable(true); 0059 m_testing = false; 0060 Q_EMIT testingChanged(); 0061 m_supportsSso = m_connection->supportsSso(); 0062 m_supportsPassword = m_connection->supportsPasswordAuth(); 0063 Q_EMIT loginFlowsChanged(); 0064 }); 0065 }); 0066 connect(m_connection, &Connection::connected, this, [this] { 0067 Q_EMIT connected(); 0068 m_isLoggingIn = false; 0069 Q_EMIT isLoggingInChanged(); 0070 Q_ASSERT(m_connection); 0071 AccountSettings account(m_connection->userId()); 0072 account.setKeepLoggedIn(true); 0073 account.setHomeserver(m_connection->homeserver()); 0074 account.setDeviceId(m_connection->deviceId()); 0075 account.setDeviceName(m_deviceName); 0076 if (!Controller::instance().saveAccessTokenToKeyChain(account, m_connection->accessToken())) { 0077 qWarning() << "Couldn't save access token"; 0078 } 0079 account.sync(); 0080 Controller::instance().addConnection(m_connection); 0081 Controller::instance().setActiveConnection(m_connection); 0082 m_connection = nullptr; 0083 }); 0084 connect(m_connection, &Connection::networkError, this, [this](QString error, const QString &, int, int) { 0085 Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error)); 0086 m_isLoggingIn = false; 0087 Q_EMIT isLoggingInChanged(); 0088 }); 0089 connect(m_connection, &Connection::loginError, this, [this](QString error, const QString &) { 0090 if (error == QStringLiteral("Invalid username or password")) { 0091 setInvalidPassword(true); 0092 } else { 0093 Q_EMIT errorOccured(i18n("Login Failed: %1", error)); 0094 } 0095 m_isLoggingIn = false; 0096 Q_EMIT isLoggingInChanged(); 0097 }); 0098 0099 connect(m_connection, &Connection::resolveError, this, [](QString error) { 0100 Q_EMIT Controller::instance().errorOccured(i18n("Network Error"), std::move(error)); 0101 }); 0102 0103 connectSingleShot(m_connection, &Connection::syncDone, this, [this]() { 0104 Q_EMIT loaded(); 0105 }); 0106 } 0107 0108 void LoginHelper::setHomeserverReachable(bool reachable) 0109 { 0110 m_homeserverReachable = reachable; 0111 Q_EMIT homeserverReachableChanged(); 0112 } 0113 0114 bool LoginHelper::homeserverReachable() const 0115 { 0116 return m_homeserverReachable; 0117 } 0118 0119 QString LoginHelper::matrixId() const 0120 { 0121 return m_matrixId; 0122 } 0123 0124 void LoginHelper::setMatrixId(const QString &matrixId) 0125 { 0126 m_matrixId = matrixId; 0127 if (!m_matrixId.startsWith(QLatin1Char('@'))) { 0128 m_matrixId.prepend(QLatin1Char('@')); 0129 } 0130 Q_EMIT matrixIdChanged(); 0131 } 0132 0133 QString LoginHelper::password() const 0134 { 0135 return m_password; 0136 } 0137 0138 void LoginHelper::setPassword(const QString &password) 0139 { 0140 setInvalidPassword(false); 0141 m_password = password; 0142 Q_EMIT passwordChanged(); 0143 } 0144 0145 QString LoginHelper::deviceName() const 0146 { 0147 return m_deviceName; 0148 } 0149 0150 void LoginHelper::setDeviceName(const QString &deviceName) 0151 { 0152 m_deviceName = deviceName; 0153 Q_EMIT deviceNameChanged(); 0154 } 0155 0156 void LoginHelper::login() 0157 { 0158 m_isLoggingIn = true; 0159 Q_EMIT isLoggingInChanged(); 0160 0161 // Some servers do not have a .well_known file. So we login via the username part from the mxid, 0162 // rather than with the full mxid, as that would lead to an invalid user. 0163 auto username = m_matrixId.mid(1, m_matrixId.indexOf(QLatin1Char(':')) - 1); 0164 m_connection->loginWithPassword(username, m_password, m_deviceName, QString()); 0165 } 0166 0167 bool LoginHelper::supportsPassword() const 0168 { 0169 return m_supportsPassword; 0170 } 0171 0172 bool LoginHelper::supportsSso() const 0173 { 0174 return m_supportsSso; 0175 } 0176 0177 QUrl LoginHelper::ssoUrl() const 0178 { 0179 return m_ssoUrl; 0180 } 0181 0182 void LoginHelper::loginWithSso() 0183 { 0184 m_connection->resolveServer(m_matrixId); 0185 connectSingleShot(m_connection, &Connection::loginFlowsChanged, this, [this]() { 0186 SsoSession *session = m_connection->prepareForSso(m_deviceName); 0187 m_ssoUrl = session->ssoUrl(); 0188 Q_EMIT ssoUrlChanged(); 0189 }); 0190 } 0191 0192 bool LoginHelper::testing() const 0193 { 0194 return m_testing; 0195 } 0196 0197 bool LoginHelper::isLoggingIn() const 0198 { 0199 return m_isLoggingIn; 0200 } 0201 0202 bool LoginHelper::isLoggedIn() const 0203 { 0204 return m_isLoggedIn; 0205 } 0206 0207 void LoginHelper::setInvalidPassword(bool invalid) 0208 { 0209 m_invalidPassword = invalid; 0210 Q_EMIT isInvalidPasswordChanged(); 0211 } 0212 0213 bool LoginHelper::isInvalidPassword() const 0214 { 0215 return m_invalidPassword; 0216 } 0217 0218 #include "moc_login.cpp"