File indexing completed on 2024-10-06 12:54:05
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 Login::Login(QObject *parent) 0017 : QObject(parent) 0018 { 0019 init(); 0020 } 0021 0022 void Login::init() 0023 { 0024 m_homeserverReachable = false; 0025 m_connection = new Connection(); 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, &Login::matrixIdChanged, this, [this]() { 0035 setHomeserverReachable(false); 0036 QRegularExpression validator("^\\@?[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 == "@") { 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 Connection(); 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().globalErrorOccured(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 Q_EMIT errorOccured(i18n("Login Failed: %1", error)); 0091 m_isLoggingIn = false; 0092 Q_EMIT isLoggingInChanged(); 0093 }); 0094 0095 connect(m_connection, &Connection::resolveError, this, [](QString error) { 0096 Q_EMIT Controller::instance().globalErrorOccured(i18n("Network Error"), std::move(error)); 0097 }); 0098 0099 connectSingleShot(m_connection, &Connection::syncDone, this, []() { 0100 Q_EMIT Controller::instance().initiated(); 0101 }); 0102 } 0103 0104 void Login::setHomeserverReachable(bool reachable) 0105 { 0106 m_homeserverReachable = reachable; 0107 Q_EMIT homeserverReachableChanged(); 0108 } 0109 0110 bool Login::homeserverReachable() const 0111 { 0112 return m_homeserverReachable; 0113 } 0114 0115 QString Login::matrixId() const 0116 { 0117 return m_matrixId; 0118 } 0119 0120 void Login::setMatrixId(const QString &matrixId) 0121 { 0122 m_matrixId = matrixId; 0123 if (!m_matrixId.startsWith('@')) { 0124 m_matrixId.prepend('@'); 0125 } 0126 Q_EMIT matrixIdChanged(); 0127 } 0128 0129 QString Login::password() const 0130 { 0131 return m_password; 0132 } 0133 0134 void Login::setPassword(const QString &password) 0135 { 0136 m_password = password; 0137 Q_EMIT passwordChanged(); 0138 } 0139 0140 QString Login::deviceName() const 0141 { 0142 return m_deviceName; 0143 } 0144 0145 void Login::setDeviceName(const QString &deviceName) 0146 { 0147 m_deviceName = deviceName; 0148 Q_EMIT deviceNameChanged(); 0149 } 0150 0151 void Login::login() 0152 { 0153 m_isLoggingIn = true; 0154 Q_EMIT isLoggingInChanged(); 0155 0156 // Some servers do not have a .well_known file. So we login via the username part from the mxid, 0157 // rather than with the full mxid, as that would lead to an invalid user. 0158 auto username = m_matrixId.mid(1, m_matrixId.indexOf(":") - 1); 0159 m_connection->loginWithPassword(username, m_password, m_deviceName, QString()); 0160 } 0161 0162 bool Login::supportsPassword() const 0163 { 0164 return m_supportsPassword; 0165 } 0166 0167 bool Login::supportsSso() const 0168 { 0169 return m_supportsSso; 0170 } 0171 0172 QUrl Login::ssoUrl() const 0173 { 0174 return m_ssoUrl; 0175 } 0176 0177 void Login::loginWithSso() 0178 { 0179 m_connection->resolveServer(m_matrixId); 0180 connectSingleShot(m_connection, &Connection::loginFlowsChanged, this, [this]() { 0181 SsoSession *session = m_connection->prepareForSso(m_deviceName); 0182 m_ssoUrl = session->ssoUrl(); 0183 Q_EMIT ssoUrlChanged(); 0184 }); 0185 } 0186 0187 bool Login::testing() const 0188 { 0189 return m_testing; 0190 } 0191 0192 bool Login::isLoggingIn() const 0193 { 0194 return m_isLoggingIn; 0195 } 0196 0197 bool Login::isLoggedIn() const 0198 { 0199 return m_isLoggedIn; 0200 } 0201 0202 #include "moc_login.cpp"