diff options
Diffstat (limited to 'src/AuthDialog.cpp')
-rw-r--r-- | src/AuthDialog.cpp | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/AuthDialog.cpp b/src/AuthDialog.cpp new file mode 100644 index 0000000..f2c4886 --- /dev/null +++ b/src/AuthDialog.cpp @@ -0,0 +1,377 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Gökçen Eraslan <gokcen@pardus.org.tr> + Copyright (C) 2008 Dirk Mueller <mueller@kde.org> + Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br> + Copyright (C) 2008-2010 Dario Freddi <drf@kde.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) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "AuthDialog.h" + +#include <QtCore/QProcess> +#include <QtGui/QPainter> +#include <QtGui/QStandardItemModel> +#include <KDebug> + +#include <KToolInvocation> +#include <KUser> + +#include <PolkitQt1/Authority> +#include <PolkitQt1/Details> + +#include <KWindowSystem> +#include <KNotification> + +AuthDialog::AuthDialog(const QString &actionId, + const QString &message, + const QString &iconName, + const PolkitQt1::Details &details, + const PolkitQt1::Identity::List &identities, + WId parent) + : KDialog(0) +{ + // KAuth is able to circumvent polkit's limitations, and manages to send the wId to the auth agent. + // If we received it, we use KWindowSystem to associate this dialog correctly. + if (parent > 0) { + kDebug() << "Associating the dialog with " << parent << " this dialog is " << winId(); + + // Set the parent + KWindowSystem::setMainWindow(this, parent); + + // Set modal + KWindowSystem::setState(winId(), NET::Modal); + } + + setupUi(mainWidget()); + setButtons(Ok | Cancel | Details); + + if (message.isEmpty()) { + kWarning() << "Could not get action message for action."; + lblHeader->hide(); + } else { + kDebug() << "Message of action: " << message; + lblHeader->setText("<h3>" + message + "</h3>"); + setCaption(message); + m_message = message; + } + + // loads the standard key icon + QPixmap icon = KIconLoader::global()->loadIcon("dialog-password", + KIconLoader::NoGroup, + KIconLoader::SizeHuge, + KIconLoader::DefaultState); + // create a painter to paint the action icon over the key icon + QPainter painter(&icon); + const int iconSize = icon.size().width(); + // the the emblem icon to size 32 + int overlaySize = 32; + // try to load the action icon + const QPixmap pixmap = KIconLoader::global()->loadIcon(iconName, + KIconLoader::NoGroup, + overlaySize, + KIconLoader::DefaultState, + QStringList(), + 0, + true); + // if we're able to load the action icon paint it over the + // key icon. + if (!pixmap.isNull()) { + QPoint startPoint; + // bottom right corner + startPoint = QPoint(iconSize - overlaySize - 2, + iconSize - overlaySize - 2); + painter.drawPixmap(startPoint, pixmap); + } + + setWindowIcon(icon); + lblPixmap->setPixmap(icon); + + // find action description for actionId + foreach(const PolkitQt1::ActionDescription &desc, PolkitQt1::Authority::instance()->enumerateActionsSync()) { + if (actionId == desc.actionId()) { + m_actionDescription = desc; + kDebug() << "Action description has been found" ; + break; + } + } + + AuthDetails *detailsDialog = new AuthDetails(details, m_actionDescription, m_appname, this); + setDetailsWidget(detailsDialog); + + userCB->hide(); + lePassword->setFocus(); + + errorMessageKTW->hide(); + + // If there is more than 1 identity we will show the combobox for user selection + if (identities.size() > 1) { + connect(userCB, SIGNAL(currentIndexChanged(int)), + this, SLOT(on_userCB_currentIndexChanged(int))); + + createUserCB(identities); + } else { + userCB->addItem("", QVariant(identities[0].toString())); + userCB->setCurrentIndex(0); + } +} + +AuthDialog::~AuthDialog() +{ +} + +void AuthDialog::accept() +{ + // Do nothing, do not close the dialog. This is needed so that the dialog stays + lePassword->setEnabled(false); + return; +} + +void AuthDialog::setRequest(const QString &request, bool requiresAdmin) +{ + kDebug() << request; + PolkitQt1::Identity identity = adminUserSelected(); + if (request.startsWith(QLatin1String("password:"), Qt::CaseInsensitive)) { + if (requiresAdmin) { + if (!identity.isValid()) { + lblPassword->setText(i18n("Password for root:")); + } else { + lblPassword->setText(i18n("Password for %1:", + identity.toString().remove("unix-user:"))); + } + } else { + lblPassword->setText(i18n("Password:")); + } + } else if (request.startsWith(QLatin1String("password or swipe finger:"), + Qt::CaseInsensitive)) { + if (requiresAdmin) { + if (!identity.isValid()) { + lblPassword->setText(i18n("Password or swipe finger for root:")); + } else { + lblPassword->setText(i18n("Password or swipe finger for %1:", + identity.toString().remove("unix-user:"))); + } + } else { + lblPassword->setText(i18n("Password or swipe finger:")); + } + } else { + lblPassword->setText(request); + } + +} + +void AuthDialog::setOptions() +{ + lblContent->setText(i18n("An application is attempting to perform an action that requires privileges." + " Authentication is required to perform this action.")); +} + +void AuthDialog::createUserCB(const PolkitQt1::Identity::List &identities) +{ + /* if we've already built the list of admin users once, then avoid + * doing it again.. (this is mainly used when the user entered the + * wrong password and the dialog is recycled) + */ + if (identities.count() && (userCB->count() - 1) != identities.count()) { + // Clears the combobox in the case some user be added + userCB->clear(); + + // Adds a Dummy user + userCB->addItem(i18n("Select User"), qVariantFromValue<QString> (QString())); + qobject_cast<QStandardItemModel *>(userCB->model())->item(userCB->count()-1)->setEnabled(false); + + // For each user + int index = 1; // Start at 1 because of the "Select User" entry + int currentUserIndex = -1; + const KUser currentUser; + foreach(const PolkitQt1::Identity &identity, identities) { + // First check to see if the user is valid + kDebug() << "User: " << identity.toString(); + const KUser user(identity.toString().remove("unix-user:")); + if (!user.isValid()) { + kWarning() << "User invalid: " << user.loginName(); + continue; + } + + // Display user Full Name IF available + QString display; + if (!user.property(KUser::FullName).toString().isEmpty()) { + display = i18nc("%1 is the full user name, %2 is the user login name", "%1 (%2)", user.property(KUser::FullName).toString(), user.loginName()); + } else { + display = user.loginName(); + } + + KIcon icon; + // load user icon face + if (!user.faceIconPath().isEmpty()) { + icon = KIcon(user.faceIconPath()); + } else { + icon = KIcon("user-identity"); + } + // appends the user item + userCB->addItem(icon, display, qVariantFromValue<QString> (identity.toString())); + + if (user == currentUser) { + currentUserIndex = index; + } + ++index; + } + + // Show the widget and set focus + if (currentUserIndex != -1) { + userCB->setCurrentIndex(currentUserIndex); + } + userCB->show(); + } +} + +PolkitQt1::Identity AuthDialog::adminUserSelected() const +{ + if (userCB->currentIndex() == -1) + return PolkitQt1::Identity(); + + QString id = userCB->itemData(userCB->currentIndex()).toString(); + if (id.isEmpty()) + return PolkitQt1::Identity(); + return PolkitQt1::Identity::fromString(id); +} + +void AuthDialog::on_userCB_currentIndexChanged(int /*index*/) +{ + PolkitQt1::Identity identity = adminUserSelected(); + // itemData is Null when "Select user" is selected + if (!identity.isValid()) { + lePassword->setEnabled(false); + lblPassword->setEnabled(false); + enableButtonOk(false); + } else { + lePassword->setEnabled(true); + lblPassword->setEnabled(true); + enableButtonOk(true); + // We need this to restart the auth with the new user + emit adminUserSelected(identity); + // git password label focus + lePassword->setFocus(); + } +} + +QString AuthDialog::password() const +{ + return lePassword->text(); +} + +void AuthDialog::authenticationFailure() +{ + errorMessageKTW->setText(i18n("Authentication failure, please try again."), KTitleWidget::ErrorMessage); + QFont bold = font(); + bold.setBold(true); + lblPassword->setFont(bold); + lePassword->setEnabled(true); + lePassword->clear(); + lePassword->setFocus(); +} + +void AuthDialog::showEvent(QShowEvent *event) +{ + KDialog::showEvent(event); + if (winId() != KWindowSystem::activeWindow()) + { + KNotification *notification = new KNotification("authenticate", this, + KNotification::Persistent | KNotification::CloseWhenWidgetActivated); + kDebug() << "Notificate: " << notification->eventId(); + notification->setText(m_message); + QPixmap icon = KIconLoader::global()->loadIcon("dialog-password", + KIconLoader::NoGroup, + KIconLoader::SizeHuge, + KIconLoader::DefaultState); + notification->setPixmap(icon); + notification->setActions(QStringList() << i18n("Switch to dialog") << i18n("Cancel")); + + connect(notification, SIGNAL(activated(uint)), this, SLOT(notificationActivated(uint))); + notification->sendEvent(); + } + +} + +void AuthDialog::notificationActivated(unsigned int action) +{ + kDebug() << "notificationActivated: " << action; + if (action == 1) + { + KWindowSystem::forceActiveWindow(winId()); + } +} + +AuthDetails::AuthDetails(const PolkitQt1::Details &details, + const PolkitQt1::ActionDescription &actionDescription, + const QString &appname, + QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + app_label->setText(appname); + + foreach(const QString &key, details.keys()) { //krazy:exclude=foreach (Details is not a map/hash, but rather a method) + int row = gridLayout->rowCount() + 1; + + QLabel *keyLabel = new QLabel(this); + keyLabel->setText(i18nc("%1 is the name of a detail about the current action " + "provided by polkit", "%1:", key)); + gridLayout->addWidget(keyLabel, row, 0); + + QLabel *valueLabel = new QLabel(this); + valueLabel->setText(details.lookup(key)); + gridLayout->addWidget(valueLabel, row, 1); + } + + action_label->setText(actionDescription.description()); + + action_label->setTipText(i18n("Click to edit %1", actionDescription.actionId())); + action_label->setUrl(actionDescription.actionId()); + + QString vendor = actionDescription.vendorName(); + QString vendorUrl = actionDescription.vendorUrl(); + + if (!vendor.isEmpty()) { + vendorUL->setText(vendor); + vendorUL->setTipText(i18n("Click to open %1", vendorUrl)); + vendorUL->setUrl(vendorUrl); + } else if (!vendorUrl.isEmpty()) { + vendorUL->setText(vendorUrl); + vendorUL->setTipText(i18n("Click to open %1", vendorUrl)); + vendorUL->setUrl(vendorUrl); + } else { + vendorL->hide(); + vendorUL->hide(); + } + + connect(vendorUL, SIGNAL(leftClickedUrl(QString)), SLOT(openUrl(QString))); + connect(action_label, SIGNAL(leftClickedUrl(QString)), SLOT(openAction(QString))); +} + +void AuthDetails::openUrl(const QString& url) +{ + KToolInvocation::invokeBrowser(url); +} + +void AuthDetails::openAction(const QString &url) +{ + QProcess::startDetached("polkit-kde-authorization", QStringList() << url); +} + +#include "AuthDialog.moc" |