From 921321156c2f1ceed0e02d519a1835e63e8c8b48 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Wed, 11 Mar 2015 19:49:27 +0100 Subject: [PATCH] Provide a proper dialog for changing the core password The password change dialog now asks for your old password, and forces you to confirm the new password by typing it twice, as is customary. To make this works, we need to add bidirectional communication between client and core, forcing some more changes to the way the first iteration of the feature was done. Note that this commit breaks compatibility with the previous implementation. If you run a beta1 core or client, you need to upgrade both to make things work again. Since no real release happened in between, I don't deem it necessary to provide backwards compat or yet another feature guard. --- src/client/client.cpp | 22 ++++-- src/client/client.h | 10 ++- src/core/core.cpp | 10 ++- src/core/core.h | 9 +++ src/core/coresession.cpp | 12 ++- src/core/coresession.h | 8 +- src/core/sessionthread.cpp | 1 - src/core/sessionthread.h | 2 - src/qtui/CMakeLists.txt | 2 + src/qtui/mainwin.cpp | 14 ++-- src/qtui/mainwin.h | 4 +- src/qtui/passwordchangedlg.cpp | 75 +++++++++++++++++++ src/qtui/passwordchangedlg.h | 42 +++++++++++ src/qtui/ui/passwordchangedlg.ui | 124 +++++++++++++++++++++++++++++++ 14 files changed, 301 insertions(+), 34 deletions(-) create mode 100644 src/qtui/passwordchangedlg.cpp create mode 100644 src/qtui/passwordchangedlg.h create mode 100644 src/qtui/ui/passwordchangedlg.ui diff --git a/src/client/client.cpp b/src/client/client.cpp index d8dbcbf5..54a93fb3 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -153,6 +153,9 @@ void Client::init() p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); + p->attachSignal(this, SIGNAL(requestPasswordChange(PeerPtr,QString,QString,QString)), SIGNAL(changePassword(PeerPtr,QString,QString,QString))); + p->attachSlot(SIGNAL(passwordChanged(PeerPtr,bool)), this, SLOT(corePasswordChanged(PeerPtr,bool))); + //connect(mainUi(), SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &))); connect(mainUi(), SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore())); connect(this, SIGNAL(connected()), mainUi(), SLOT(connectedToCore())); @@ -386,11 +389,6 @@ void Client::setSyncedToCore() connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); SignalProxy *p = signalProxy(); - - if ((Client::coreFeatures() & Quassel::PasswordChange)) { - p->attachSignal(this, SIGNAL(clientChangePassword(QString))); - } - p->synchronize(bufferSyncer()); // create a new BufferViewManager @@ -653,12 +651,20 @@ void Client::markBufferAsRead(BufferId id) bufferSyncer()->requestMarkBufferAsRead(id); } -void Client::changePassword(QString newPassword) { + +void Client::changePassword(const QString &oldPassword, const QString &newPassword) { CoreAccount account = currentCoreAccount(); account.setPassword(newPassword); coreAccountModel()->createOrUpdateAccount(account); - coreAccountModel()->save(); - emit clientChangePassword(newPassword); + emit instance()->requestPasswordChange(nullptr, account.user(), oldPassword, newPassword); +} + + +void Client::corePasswordChanged(PeerPtr, bool success) +{ + if (success) + coreAccountModel()->save(); + emit passwordChanged(success); } diff --git a/src/client/client.h b/src/client/client.h index 445648b2..6d224cf9 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -142,6 +142,8 @@ public: static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); static void purgeKnownBufferIds(); + static void changePassword(const QString &oldPassword, const QString &newPassword); + #if QT_VERSION < 0x050000 static void logMessage(QtMsgType type, const char *msg); #else @@ -191,7 +193,9 @@ signals: */ void bufferMarkedAsRead(BufferId id); - void clientChangePassword(QString password); + //! Requests a password change (user name must match the currently logged in user) + void requestPasswordChange(PeerPtr peer, const QString &userName, const QString &oldPassword, const QString &newPassword); + void passwordChanged(bool success); public slots: void disconnectFromCore(); @@ -202,8 +206,6 @@ public slots: void markBufferAsRead(BufferId id); - void changePassword(QString newPassword); - private slots: void setSyncedToCore(); void setDisconnectedFromCore(); @@ -218,6 +220,8 @@ private slots: void coreNetworkCreated(NetworkId); void coreNetworkRemoved(NetworkId); + void corePasswordChanged(PeerPtr, bool success); + void requestInitialBacklog(); void sendBufferedUserInput(); diff --git a/src/core/core.cpp b/src/core/core.cpp index dfd2c95a..2049b63b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -638,7 +638,6 @@ SessionThread *Core::sessionForUser(UserId uid, bool restore) SessionThread *session = new SessionThread(uid, restore, this); _sessions[uid] = session; session->start(); - connect(session, SIGNAL(passwordChangeRequested(UserId, QString)), _storage, SLOT(updateUser(UserId, QString))); return session; } @@ -819,6 +818,15 @@ void Core::changeUserPass(const QString &username) } +bool Core::changeUserPassword(UserId userId, const QString &password) +{ + if (!isConfigured() || !userId.isValid()) + return false; + + return instance()->_storage->updateUser(userId, password); +} + + AbstractSqlMigrationReader *Core::getMigrationReader(Storage *storage) { if (!storage) diff --git a/src/core/core.h b/src/core/core.h index deef9114..e356a0fb 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -74,6 +74,15 @@ public: return instance()->_storage->validateUser(userName, password); } + + //! Change a user's password + /** + * \param userId The user's ID + * \param password The user's unencrypted new password + * \return true, if the password change was successful + */ + static bool changeUserPassword(UserId userId, const QString &password); + //! Store a user setting persistently /** * \param userId The users Id diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 1f6345d0..5fd5bdcf 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -100,7 +100,8 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &))); p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId))); - p->attachSlot(SIGNAL(clientChangePassword(QString)), this, SLOT(changePassword(QString))); + p->attachSlot(SIGNAL(changePassword(PeerPtr,QString,QString,QString)), this, SLOT(changePassword(PeerPtr,QString,QString,QString))); + p->attachSignal(this, SIGNAL(passwordChanged(PeerPtr,bool))); loadSettings(); initScriptEngine(); @@ -641,7 +642,12 @@ void CoreSession::globalAway(const QString &msg) } } -void CoreSession::changePassword(QString password) +void CoreSession::changePassword(PeerPtr peer, const QString &userName, const QString &oldPassword, const QString &newPassword) { - emit passwordChangeRequested(_user, password); + bool success = false; + UserId uid = Core::validateUser(userName, oldPassword); + if (uid.isValid() && uid == user()) + success = Core::changeUserPassword(uid, newPassword); + + emit passwordChanged(peer, success); } diff --git a/src/core/coresession.h b/src/core/coresession.h index 0861b18c..a164ffe1 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -27,6 +27,7 @@ #include "corecoreinfo.h" #include "corealiasmanager.h" #include "coreignorelistmanager.h" +#include "peer.h" #include "protocol.h" #include "message.h" #include "storage.h" @@ -45,7 +46,6 @@ class EventManager; class EventStringifier; class InternalPeer; class IrcParser; -class Peer; class MessageEvent; class NetworkConnection; class RemotePeer; @@ -127,13 +127,13 @@ public slots: */ void renameBuffer(const NetworkId &networkId, const QString &newName, const QString &oldName); + void changePassword(PeerPtr peer, const QString &userName, const QString &oldPassword, const QString &newPassword); + QHash persistentChannels(NetworkId) const; //! Marks us away (or unaway) on all networks void globalAway(const QString &msg = QString()); - void changePassword(QString password); - signals: void initialized(); void sessionState(const Protocol::SessionState &sessionState); @@ -160,7 +160,7 @@ signals: void networkRemoved(NetworkId); void networkDisconnected(NetworkId); - void passwordChangeRequested(UserId user, QString password); + void passwordChanged(PeerPtr peer, bool success); protected: virtual void customEvent(QEvent *event); diff --git a/src/core/sessionthread.cpp b/src/core/sessionthread.cpp index 1439bfce..c2f9b5a2 100644 --- a/src/core/sessionthread.cpp +++ b/src/core/sessionthread.cpp @@ -121,7 +121,6 @@ void SessionThread::addInternalClientToSession(InternalPeer *internalPeer) void SessionThread::run() { _session = new CoreSession(user(), _restoreState); - connect(_session, SIGNAL(passwordChangeRequested(UserId, QString)), SIGNAL(passwordChangeRequested(UserId, QString))); connect(this, SIGNAL(addRemoteClient(RemotePeer*)), _session, SLOT(addClient(RemotePeer*))); connect(this, SIGNAL(addInternalClient(InternalPeer*)), _session, SLOT(addClient(InternalPeer*))); connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState))); diff --git a/src/core/sessionthread.h b/src/core/sessionthread.h index 9a4a1b6b..fee6e64f 100644 --- a/src/core/sessionthread.h +++ b/src/core/sessionthread.h @@ -57,8 +57,6 @@ signals: void addRemoteClient(RemotePeer *peer); void addInternalClient(InternalPeer *peer); - void passwordChangeRequested(UserId user, QString newPassword); - private: CoreSession *_session; UserId _user; diff --git a/src/qtui/CMakeLists.txt b/src/qtui/CMakeLists.txt index f17cd454..be9a14b5 100644 --- a/src/qtui/CMakeLists.txt +++ b/src/qtui/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCES markerlineitem.cpp msgprocessorstatuswidget.cpp nicklistwidget.cpp + passwordchangedlg.cpp qtui.cpp qtuiapplication.cpp qtuimessageprocessor.cpp @@ -71,6 +72,7 @@ set(FORMS inputwidget.ui msgprocessorstatuswidget.ui nicklistwidget.ui + passwordchangedlg.ui settingsdlg.ui settingspagedlg.ui simplenetworkeditor.ui diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index 84c31597..8f022cac 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -87,6 +87,7 @@ #include "legacysystemtray.h" #include "msgprocessorstatuswidget.h" #include "nicklistwidget.h" +#include "passwordchangedlg.h" #include "qtuiapplication.h" #include "qtuimessageprocessor.h" #include "qtuisettings.h" @@ -197,8 +198,6 @@ void MainWin::init() connect(Client::coreConnection(), SIGNAL(handleSslErrors(const QSslSocket *, bool *, bool *)), SLOT(handleSslErrors(const QSslSocket *, bool *, bool *))); #endif - connect(this, SIGNAL(changePassword(QString)), Client::instance(), SLOT(changePassword(QString))); - // Setup Dock Areas setDockNestingEnabled(true); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); @@ -363,7 +362,7 @@ void MainWin::setupActions() coll->addAction("DisconnectCore", new Action(QIcon::fromTheme("network-disconnect"), tr("&Disconnect from Core"), coll, Client::instance(), SLOT(disconnectFromCore()))); coll->addAction("ChangePassword", new Action(QIcon::fromTheme("dialog-password"), tr("Change &Password..."), coll, - this, SLOT(showChangePasswordDialog()))); + this, SLOT(showPasswordChangeDlg()))); coll->addAction("CoreInfo", new Action(QIcon::fromTheme("help-about"), tr("Core &Info..."), coll, this, SLOT(showCoreInfoDlg()))); coll->addAction("ConfigureNetworks", new Action(QIcon::fromTheme("configure"), tr("Configure &Networks..."), coll, @@ -738,14 +737,11 @@ void MainWin::changeActiveBufferView(int bufferViewId) } -void MainWin::showChangePasswordDialog() +void MainWin::showPasswordChangeDlg() { if((Client::coreFeatures() & Quassel::PasswordChange)) { - bool ok; - QString newPassword = QInputDialog::getText(this, tr("Set Core Password"), tr("New password for your Quassel Core:"), QLineEdit::Password, QString(), &ok); - if (ok && !newPassword.isEmpty()) { - emit changePassword(newPassword); - } + PasswordChangeDlg dlg(this); + dlg.exec(); } else { QMessageBox box(QMessageBox::Warning, tr("Feature Not Supported"), diff --git a/src/qtui/mainwin.h b/src/qtui/mainwin.h index 44444266..900354b1 100644 --- a/src/qtui/mainwin.h +++ b/src/qtui/mainwin.h @@ -123,6 +123,7 @@ private slots: void showNotificationsDlg(); void showIgnoreList(QString newRule = QString()); void showShortcutsDlg(); + void showPasswordChangeDlg(); void showNewTransferDlg(const ClientTransfer *transfer); void onFullScreenToggled(); @@ -164,12 +165,9 @@ private slots: void changeActiveBufferView(bool backwards); void changeActiveBufferView(int bufferViewId); - void showChangePasswordDialog(); - signals: void connectToCore(const QVariantMap &connInfo); void disconnectFromCore(); - void changePassword(QString newPassword); private: #ifdef HAVE_KDE diff --git a/src/qtui/passwordchangedlg.cpp b/src/qtui/passwordchangedlg.cpp new file mode 100644 index 00000000..7009adf6 --- /dev/null +++ b/src/qtui/passwordchangedlg.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2005-2015 by the Quassel Project * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "passwordchangedlg.h" + +#include +#include + +#include "client.h" + +PasswordChangeDlg::PasswordChangeDlg(QWidget *parent) : QDialog(parent) +{ + ui.setupUi(this); + + CoreAccount account = Client::currentCoreAccount(); + ui.infoLabel->setText(tr("This changes the password for your username %1 " + "on the Quassel Core running at %2.") + .arg(account.user(), account.hostName())); + + connect(ui.oldPasswordEdit, SIGNAL(textChanged(QString)), SLOT(inputChanged())); + connect(ui.newPasswordEdit, SIGNAL(textChanged(QString)), SLOT(inputChanged())); + connect(ui.confirmPasswordEdit, SIGNAL(textChanged(QString)), SLOT(inputChanged())); + connect(ui.buttonBox, SIGNAL(accepted()), SLOT(changePassword())); + + connect(Client::instance(), SIGNAL(passwordChanged(bool)), SLOT(passwordChanged(bool))); + + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); +} + + +void PasswordChangeDlg::inputChanged() +{ + bool ok = !ui.oldPasswordEdit->text().isEmpty() && !ui.newPasswordEdit->text().isEmpty() + && ui.newPasswordEdit->text() == ui.confirmPasswordEdit->text(); + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); +} + + +void PasswordChangeDlg::changePassword() +{ + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + Client::changePassword(ui.oldPasswordEdit->text(), ui.newPasswordEdit->text()); +} + + +void PasswordChangeDlg::passwordChanged(bool success) +{ + if (!success) { + QMessageBox box(QMessageBox::Warning, tr("Password Not Changed"), + tr("Password change failed"), + QMessageBox::Ok, this); + box.setInformativeText(tr("The core reported an error when trying to change your password. Make sure you entered your old password correctly!")); + box.exec(); + } + else { + accept(); + } +} diff --git a/src/qtui/passwordchangedlg.h b/src/qtui/passwordchangedlg.h new file mode 100644 index 00000000..36bfc63b --- /dev/null +++ b/src/qtui/passwordchangedlg.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2005-2015 by the Quassel Project * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#pragma once + +#include + +#include "ui_passwordchangedlg.h" + +class PasswordChangeDlg : public QDialog +{ + Q_OBJECT + +public: + PasswordChangeDlg(QWidget *parent = nullptr); + +private slots: + void inputChanged(); + void changePassword(); + void passwordChanged(bool success); + +private: + Ui::PasswordChangeDlg ui; + QString _newPassword; +}; diff --git a/src/qtui/ui/passwordchangedlg.ui b/src/qtui/ui/passwordchangedlg.ui new file mode 100644 index 00000000..cf68c1f9 --- /dev/null +++ b/src/qtui/ui/passwordchangedlg.ui @@ -0,0 +1,124 @@ + + + PasswordChangeDlg + + + + 0 + 0 + 455 + 173 + + + + Change Password + + + + + + + + <html><head/><body><p>This changes the password for your username <span style=" font-weight:600;">John</span> on the Quassel Core running at <span style=" font-weight:600;">example.invalid</span>.</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + Old password: + + + + + + + QLineEdit::Password + + + + + + + New Password: + + + + + + + QLineEdit::Password + + + + + + + Confirm password: + + + + + + + QLineEdit::Password + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + rejected() + PasswordChangeDlg + reject() + + + 248 + 152 + + + 229 + -14 + + + + + -- 2.20.1