File indexing completed on 2024-04-28 08:48:45
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Alejandro Fiestas Olivares <afiestas@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "createaccountjob.h" 0007 0008 #include "core.h" 0009 #include "kaccountsuiplugin.h" 0010 #include "uipluginsmanager.h" 0011 0012 #include <QDebug> 0013 #include <QDir> 0014 #include <QPluginLoader> 0015 0016 #include <Accounts/AccountService> 0017 #include <Accounts/Manager> 0018 0019 #include <SignOn/AuthSession> 0020 #include <SignOn/Identity> 0021 0022 #include <KLocalizedString> 0023 0024 namespace KAccounts 0025 { 0026 0027 CreateAccountJob::CreateAccountJob(QObject *parent) 0028 : CreateAccountJob(QString(), parent) 0029 { 0030 } 0031 0032 CreateAccountJob::CreateAccountJob(const QString &providerName, QObject *parent) 0033 : KJob(parent) 0034 , m_providerName(providerName) 0035 , m_manager(new Accounts::Manager(this)) 0036 { 0037 } 0038 0039 void CreateAccountJob::start() 0040 { 0041 qDebug() << m_providerName; 0042 QMetaObject::invokeMethod(this, "processSession"); 0043 } 0044 0045 void CreateAccountJob::processSession() 0046 { 0047 m_account = m_manager->createAccount(m_providerName); 0048 Accounts::Service service; 0049 if (m_account->services().size() == 1) { 0050 service = m_account->services().at(0); 0051 } 0052 m_accInfo = new Accounts::AccountService(m_account, service, this); 0053 0054 const QString pluginName = m_account->provider().pluginName(); 0055 qDebug() << "Looking for plugin" << pluginName; 0056 if (!pluginName.isEmpty()) { 0057 loadPluginAndShowDialog(pluginName); 0058 } else { 0059 SignOn::IdentityInfo info; 0060 info.setCaption(m_providerName); 0061 info.setAccessControlList({QStringLiteral("*")}); 0062 info.setType(SignOn::IdentityInfo::Application); 0063 info.setStoreSecret(true); 0064 0065 m_identity = SignOn::Identity::newIdentity(info, this); 0066 m_identity->storeCredentials(); 0067 0068 connect(m_identity, &SignOn::Identity::info, this, &CreateAccountJob::info); 0069 connect(m_identity, &SignOn::Identity::error, [=](const SignOn::Error &err) { 0070 qDebug() << "Error storing identity:" << err.message(); 0071 }); 0072 0073 QVariantMap data = m_accInfo->authData().parameters(); 0074 data.insert(QStringLiteral("Embedded"), false); 0075 0076 SignOn::SessionData sessionData(data); 0077 SignOn::AuthSessionP session = m_identity->createSession(m_accInfo->authData().method()); 0078 qDebug() << "Starting auth session with" << m_accInfo->authData().method(); 0079 connect(session, &SignOn::AuthSession::error, this, &CreateAccountJob::sessionError); 0080 connect(session, &SignOn::AuthSession::response, this, &CreateAccountJob::sessionResponse); 0081 0082 session->process(sessionData, m_accInfo->authData().mechanism()); 0083 } 0084 } 0085 0086 void CreateAccountJob::loadPluginAndShowDialog(const QString &pluginName) 0087 { 0088 KAccountsUiPlugin *ui = KAccounts::UiPluginsManager::pluginForName(pluginName); 0089 0090 if (!ui) { 0091 qDebug() << "Plugin could not be loaded"; 0092 pluginError(i18nc("The %1 is for plugin name, eg. Could not load UI plugin", "Could not load %1 plugin, please check your installation", pluginName)); 0093 return; 0094 } 0095 0096 connect(ui, &KAccountsUiPlugin::success, this, &CreateAccountJob::pluginFinished, Qt::UniqueConnection); 0097 connect(ui, &KAccountsUiPlugin::error, this, &CreateAccountJob::pluginError, Qt::UniqueConnection); 0098 connect(ui, &KAccountsUiPlugin::canceled, this, &CreateAccountJob::pluginCancelled, Qt::UniqueConnection); 0099 connect(ui, &KAccountsUiPlugin::startAuthSession, this, &CreateAccountJob::startAuthSession, Qt::UniqueConnection); 0100 0101 ui->setProviderName(m_providerName); 0102 ui->init(KAccountsUiPlugin::NewAccountDialog); 0103 } 0104 0105 void CreateAccountJob::startAuthSession(const QVariantMap &data) 0106 { 0107 SignOn::IdentityInfo info; 0108 info.setCaption(m_providerName); 0109 info.setAccessControlList({QStringLiteral("*")}); 0110 info.setType(SignOn::IdentityInfo::Application); 0111 info.setStoreSecret(true); 0112 0113 m_identity = SignOn::Identity::newIdentity(info, this); 0114 m_identity->storeCredentials(); 0115 0116 connect(m_identity, &SignOn::Identity::info, this, &CreateAccountJob::info); 0117 connect(m_identity, &SignOn::Identity::error, [=](const SignOn::Error &err) { 0118 qDebug() << "Error storing identity:" << err.message(); 0119 }); 0120 0121 auto i = data.constBegin(); 0122 while (i != data.constEnd()) { 0123 m_account->setValue(i.key(), i.value()); 0124 ++i; 0125 } 0126 0127 m_account->syncAndBlock(); 0128 0129 QVariantMap authData = m_accInfo->authData().parameters(); 0130 authData.insert(QStringLiteral("Embedded"), false); 0131 0132 SignOn::SessionData sessionData(authData); 0133 SignOn::AuthSessionP session = m_identity->createSession(m_accInfo->authData().method()); 0134 qDebug() << "Starting auth session with" << m_accInfo->authData().method(); 0135 connect(session, &SignOn::AuthSession::error, this, &CreateAccountJob::sessionError); 0136 connect(session, &SignOn::AuthSession::response, this, &CreateAccountJob::sessionResponse); 0137 0138 session->process(sessionData, m_accInfo->authData().mechanism()); 0139 } 0140 0141 void CreateAccountJob::pluginFinished(const QString &screenName, const QString &secret, const QVariantMap &data) 0142 { 0143 // Set up the new identity 0144 SignOn::IdentityInfo info; 0145 info.setStoreSecret(true); 0146 info.setUserName(screenName); 0147 info.setSecret(secret, true); 0148 info.setCaption(m_providerName); 0149 info.setAccessControlList(QStringList(QStringLiteral("*"))); 0150 info.setType(SignOn::IdentityInfo::Application); 0151 0152 const auto keys = data.keys(); 0153 for (const QString &key : keys) { 0154 // If a key with __service/ prefix exists and its value is false, 0155 // add it to m_disabledServices which will later be used for disabling 0156 // the services contained in that list 0157 if (key.startsWith(QLatin1String("__service/")) && !data.value(key).toBool()) { 0158 m_disabledServices << key.mid(10); 0159 } 0160 m_account->setValue(key, data.value(key).toString()); 0161 } 0162 0163 m_identity = SignOn::Identity::newIdentity(info, this); 0164 connect(m_identity, &SignOn::Identity::info, this, &CreateAccountJob::info); 0165 0166 m_done = true; 0167 0168 connect(m_identity, &SignOn::Identity::credentialsStored, m_identity, &SignOn::Identity::queryInfo); 0169 m_identity->storeCredentials(); 0170 } 0171 0172 void CreateAccountJob::pluginError(const QString &error) 0173 { 0174 if (error.isEmpty()) { 0175 setError(-1); 0176 } else { 0177 setError(KJob::UserDefinedError); 0178 } 0179 setErrorText(error); 0180 // Delete the dialog 0181 emitResult(); 0182 } 0183 0184 void CreateAccountJob::pluginCancelled() 0185 { 0186 setError(KJob::KilledJobError); 0187 setErrorText(i18n("Cancelled by user")); 0188 0189 emitResult(); 0190 } 0191 0192 void CreateAccountJob::sessionResponse(const SignOn::SessionData & /*data*/) 0193 { 0194 qDebug() << "Received session response"; 0195 0196 m_done = true; 0197 m_identity->queryInfo(); 0198 } 0199 0200 void CreateAccountJob::info(const SignOn::IdentityInfo &info) 0201 { 0202 qDebug() << "Info:"; 0203 qDebug() << "\tId:" << info.id(); 0204 qDebug() << "\tcaption:" << info.caption(); 0205 qDebug() << "\towner:" << info.owner(); 0206 qDebug() << "\tuserName:" << info.userName(); 0207 0208 if (!m_done) { 0209 return; 0210 } 0211 0212 m_account->selectService(); 0213 0214 if (m_account->displayName().isEmpty()) { 0215 if (info.userName().isEmpty()) { 0216 // info.userName() can be empty, see bug#414219 0217 m_account->setDisplayName(QStringLiteral("%1%2").arg(info.caption()).arg(info.id())); 0218 } else { 0219 m_account->setDisplayName(info.userName()); 0220 } 0221 } 0222 m_account->setValue(QStringLiteral("username"), info.userName()); 0223 m_account->setCredentialsId(info.id()); 0224 0225 Accounts::AuthData authData = m_accInfo->authData(); 0226 m_account->setValue(QStringLiteral("auth/mechanism"), authData.mechanism()); 0227 m_account->setValue(QStringLiteral("auth/method"), authData.method()); 0228 0229 QString base = QStringLiteral("auth/"); 0230 base.append(authData.method()); 0231 base.append(QLatin1Char('/')); 0232 base.append(authData.mechanism()); 0233 base.append(QLatin1Char('/')); 0234 0235 QVariantMap data = authData.parameters(); 0236 QMapIterator<QString, QVariant> i(data); 0237 while (i.hasNext()) { 0238 i.next(); 0239 m_account->setValue(base + i.key(), i.value()); 0240 } 0241 0242 const Accounts::ServiceList services = m_account->services(); 0243 for (const Accounts::Service &service : services) { 0244 m_account->selectService(service); 0245 m_account->setEnabled(m_disabledServices.contains(service.name()) ? false : true); 0246 } 0247 0248 m_account->selectService(); 0249 m_account->setEnabled(true); 0250 m_account->sync(); 0251 connect(m_account, &Accounts::Account::synced, this, &CreateAccountJob::emitResult); 0252 } 0253 0254 void CreateAccountJob::sessionError(const SignOn::Error &signOnError) 0255 { 0256 if (error()) { 0257 // Guard against SignOn sending two error() signals 0258 return; 0259 } 0260 qWarning() << "Error:"; 0261 qWarning() << "\t" << signOnError.message(); 0262 0263 setError(KJob::UserDefinedError); 0264 setErrorText(i18n("There was an error while trying to process the request: %1", signOnError.message())); 0265 emitResult(); 0266 } 0267 0268 void CreateAccountJob::setProviderName(const QString &name) 0269 { 0270 if (m_providerName != name) { 0271 m_providerName = name; 0272 Q_EMIT providerNameChanged(); 0273 } 0274 } 0275 0276 };