File indexing completed on 2024-04-14 14:55:41

0001 /*
0002     This file is part of the Polkit-qt project
0003     SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
0004     SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
0005     SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "polkitqt1-gui-action.h"
0011 #include "polkitqt1-authority.h"
0012 #include "polkitqt1-subject.h"
0013 
0014 #include <QCoreApplication>
0015 
0016 namespace PolkitQt1
0017 {
0018 
0019 namespace Gui
0020 {
0021 
0022 /**
0023   * \internal
0024   */
0025 class Q_DECL_HIDDEN Action::Private
0026 {
0027 public:
0028     Private(Action *p);
0029 
0030     Action *parent;
0031 
0032     QString       actionId;
0033     Authority::Result  pkResult;
0034     qint64        targetPID;
0035 
0036     void                 updateAction();
0037     bool                 computePkResult();
0038     void                 configChanged();
0039 
0040     bool    initiallyChecked;
0041 
0042     // states data
0043     bool    selfBlockedVisible;
0044     bool    selfBlockedEnabled;
0045     QString selfBlockedText;
0046     QString selfBlockedWhatsThis;
0047     QString selfBlockedToolTip;
0048     QIcon   selfBlockedIcon;
0049 
0050     bool    noVisible;
0051     bool    noEnabled;
0052     QString noText;
0053     QString noWhatsThis;
0054     QString noToolTip;
0055     QIcon   noIcon;
0056 
0057     bool    authVisible;
0058     bool    authEnabled;
0059     QString authText;
0060     QString authWhatsThis;
0061     QString authToolTip;
0062     QIcon   authIcon;
0063 
0064     bool    yesVisible;
0065     bool    yesEnabled;
0066     QString yesText;
0067     QString yesWhatsThis;
0068     QString yesToolTip;
0069     QIcon   yesIcon;
0070 };
0071 
0072 Action::Private::Private(Action *p)
0073         : parent(p)
0074         , targetPID(getpid())
0075 {
0076     initiallyChecked = false;
0077 
0078     // Set the default values
0079     selfBlockedVisible = true;
0080     selfBlockedEnabled = false;
0081 
0082     noVisible     = true;
0083     noEnabled     = false;
0084 
0085     authVisible   = true;
0086     authEnabled   = true;
0087 
0088     yesVisible    = true;
0089     yesEnabled    = true;
0090 }
0091 
0092 Action::Action(const QString &actionId, QObject *parent)
0093         : QAction(parent)
0094         , d(new Private(this))
0095 {
0096     // this must be called AFTER the values initialization
0097     setPolkitAction(actionId);
0098 
0099     // track the config changes to update the action
0100     connect(Authority::instance(), SIGNAL(configChanged()),
0101             this, SLOT(configChanged()));
0102     // for now we call config changed..
0103     connect(Authority::instance(), SIGNAL(consoleKitDBChanged()),
0104             this, SLOT(configChanged()));
0105 }
0106 
0107 Action::~Action()
0108 {
0109     delete d;
0110 }
0111 
0112 bool Action::activate()
0113 {
0114     switch (d->pkResult) {
0115     case Authority::Yes:
0116     case Authority::Challenge:
0117         // just Q_EMIT the 'activated' signal
0118         Q_EMIT authorized();
0119         return true;
0120         break;
0121     default:
0122     case Authority::No:
0123         if (d->noEnabled) {
0124             /* If PolicyKit says no... and we got here.. it means
0125              * that the user set the property "no-enabled" to
0126              * TRUE..
0127              *
0128              * Hence, they probably have a good reason for doing
0129              * this so do let the 'activate' signal propagate..
0130              */
0131             Q_EMIT authorized();
0132             return true;
0133         }
0134         break;
0135     }
0136     return false;
0137 }
0138 
0139 void Action::setChecked(bool checked)
0140 {
0141     // We store this as initiallyChecked
0142     // to be able to undo changes in case the auth fails
0143     d->initiallyChecked = checked;
0144     QAction::setChecked(checked);
0145 }
0146 
0147 void Action::Private::updateAction()
0148 {
0149     if (Authority::instance()->hasError()) {
0150         return;
0151     }
0152 
0153     switch (pkResult) {
0154         default:
0155         case Authority::Unknown:
0156         case Authority::No:
0157             qobject_cast<QAction *>(parent)->setVisible(noVisible);
0158             qobject_cast<QAction *>(parent)->setEnabled(noEnabled);
0159             qobject_cast<QAction *>(parent)->setText(noText);
0160             if (!noWhatsThis.isNull()) {
0161                 qobject_cast<QAction *>(parent)->setWhatsThis(noWhatsThis);
0162             }
0163             if (!noToolTip.isNull()) {
0164                 qobject_cast<QAction *>(parent)->setToolTip(noToolTip);
0165             }
0166             qobject_cast<QAction *>(parent)->setIcon(noIcon);
0167             break;
0168 
0169         case Authority::Challenge:
0170             qobject_cast<QAction *>(parent)->setVisible(authVisible);
0171             qobject_cast<QAction *>(parent)->setEnabled(authEnabled);
0172             qobject_cast<QAction *>(parent)->setText(authText);
0173             if (!authWhatsThis.isNull()) {
0174                 qobject_cast<QAction *>(parent)->setWhatsThis(authWhatsThis);
0175             }
0176             if (!authToolTip.isNull()) {
0177                 qobject_cast<QAction *>(parent)->setToolTip(authToolTip);
0178             }
0179             qobject_cast<QAction *>(parent)->setIcon(authIcon);
0180             break;
0181         case Authority::Yes:
0182             qobject_cast<QAction *>(parent)->setVisible(yesVisible);
0183             qobject_cast<QAction *>(parent)->setEnabled(yesEnabled);
0184             qobject_cast<QAction *>(parent)->setText(yesText);
0185             if (!yesWhatsThis.isNull()) {
0186                 qobject_cast<QAction *>(parent)->setWhatsThis(yesWhatsThis);
0187             }
0188             if (!yesToolTip.isNull()) {
0189                 qobject_cast<QAction *>(parent)->setToolTip(yesToolTip);
0190             }
0191             qobject_cast<QAction *>(parent)->setIcon(yesIcon);
0192             if (parent->isCheckable()) {
0193                 qobject_cast<QAction *>(parent)->setChecked(!initiallyChecked);
0194             }
0195             break;
0196     }
0197     Q_EMIT parent->dataChanged();
0198 }
0199 
0200 void Action::Private::configChanged()
0201 {
0202     bool result_changed;
0203     result_changed = computePkResult();
0204     if (result_changed) {
0205         updateAction();
0206     }
0207 }
0208 
0209 bool Action::Private::computePkResult()
0210 {
0211     Authority::Result old_result;
0212     UnixProcessSubject subject(parent->targetPID());
0213 
0214     old_result = pkResult;
0215     pkResult = Authority::Unknown;
0216 
0217     pkResult = Authority::instance()->checkAuthorizationSync(actionId, subject, Authority::None);
0218 
0219     return old_result != pkResult;
0220 }
0221 
0222 qint64 Action::targetPID() const
0223 {
0224     if (d->targetPID != 0) {
0225         return d->targetPID;
0226     } else {
0227         return QCoreApplication::applicationPid();
0228     }
0229 }
0230 
0231 void Action::setTargetPID(qint64 pid)
0232 {
0233     d->targetPID = pid;
0234 
0235     d->computePkResult();
0236     d->updateAction();
0237 }
0238 
0239 bool Action::isAllowed() const
0240 {
0241     return d->pkResult == Authority::Yes;
0242 }
0243 
0244 bool Action::is(const QString &other) const
0245 {
0246     return d->actionId == other;
0247 }
0248 
0249 void Action::revoke()
0250 {
0251     /*TODO: implement it? no negative authorizations available, no authorization db*/
0252 }
0253 
0254 void Action::setText(const QString &text, States states)
0255 {
0256     if (states & All) {
0257         d->selfBlockedText = text;
0258         d->noText = text;
0259         d->authText = text;
0260         d->yesText = text;
0261     } else if (states & Auth) {
0262         d->authText = text;
0263     } else if (states & No) {
0264         d->noText = text;
0265     } else if (states & SelfBlocked) {
0266         d->selfBlockedText = text;
0267     } else if (states & Yes) {
0268         d->yesText = text;
0269     }
0270 
0271     d->updateAction();
0272 }
0273 
0274 QString Action::text(Action::State state) const
0275 {
0276     switch (state) {
0277         case Yes:
0278             return d->yesText;
0279         case No:
0280             return d->noText;
0281         case Auth:
0282             return d->authText;
0283         case SelfBlocked:
0284             return d->selfBlockedText;
0285         case None:
0286             return QAction::text();
0287         default:
0288             return QString();
0289     }
0290 }
0291 
0292 void Action::setToolTip(const QString &toolTip, States states)
0293 {
0294     if (states & All) {
0295         d->selfBlockedToolTip = toolTip;
0296         d->noToolTip = toolTip;
0297         d->authToolTip = toolTip;
0298         d->yesToolTip = toolTip;
0299     } else if (states & Auth) {
0300         d->authToolTip = toolTip;
0301     } else if (states & No) {
0302         d->noToolTip = toolTip;
0303     } else if (states & SelfBlocked) {
0304         d->selfBlockedToolTip = toolTip;
0305     } else if (states & Yes) {
0306         d->yesToolTip = toolTip;
0307     }
0308 
0309     d->updateAction();
0310 }
0311 
0312 QString Action::toolTip(Action::State state) const
0313 {
0314     switch (state) {
0315         case Yes:
0316             return d->yesToolTip;
0317         case No:
0318             return d->noToolTip;
0319         case Auth:
0320             return d->authToolTip;
0321         case SelfBlocked:
0322             return d->selfBlockedToolTip;
0323         case None:
0324             return QAction::toolTip();
0325         default:
0326             return QString();
0327     }
0328 }
0329 
0330 void Action::setWhatsThis(const QString &whatsThis, States states)
0331 {
0332     if (states & All) {
0333         d->selfBlockedWhatsThis = whatsThis;
0334         d->noWhatsThis = whatsThis;
0335         d->authWhatsThis = whatsThis;
0336         d->yesWhatsThis = whatsThis;
0337     } else if (states & Auth) {
0338         d->authWhatsThis = whatsThis;
0339     } else if (states & No) {
0340         d->noWhatsThis = whatsThis;
0341     } else if (states & SelfBlocked) {
0342         d->selfBlockedWhatsThis = whatsThis;
0343     } else if (states & Yes) {
0344         d->yesWhatsThis = whatsThis;
0345     }
0346 
0347     d->updateAction();
0348 }
0349 
0350 QString Action::whatsThis(Action::State state) const
0351 {
0352     switch (state) {
0353         case Yes:
0354             return d->yesWhatsThis;
0355         case No:
0356             return d->noWhatsThis;
0357         case Auth:
0358             return d->authWhatsThis;
0359         case SelfBlocked:
0360             return d->selfBlockedWhatsThis;
0361         case None:
0362             return QAction::whatsThis();
0363         default:
0364             return QString();
0365     }
0366 }
0367 
0368 void Action::setIcon(const QIcon &icon, States states)
0369 {
0370     if (states & All) {
0371         d->selfBlockedIcon = icon;
0372         d->noIcon = icon;
0373         d->authIcon = icon;
0374         d->yesIcon = icon;
0375     } else if (states & Auth) {
0376         d->authIcon = icon;
0377     } else if (states & No) {
0378         d->noIcon = icon;
0379     } else if (states & SelfBlocked) {
0380         d->selfBlockedIcon = icon;
0381     } else if (states & Yes) {
0382         d->yesIcon = icon;
0383     }
0384 
0385     d->updateAction();
0386 }
0387 
0388 QIcon Action::icon(Action::State state) const
0389 {
0390     switch (state) {
0391         case Yes:
0392             return d->yesIcon;
0393         case No:
0394             return d->noIcon;
0395         case Auth:
0396             return d->authIcon;
0397         case SelfBlocked:
0398             return d->selfBlockedIcon;
0399         case None:
0400             return QAction::icon();
0401         default:
0402             return QIcon();
0403     }
0404 }
0405 
0406 void Action::setEnabled(bool enabled, States states)
0407 {
0408     if (states & All) {
0409         d->selfBlockedEnabled = enabled;
0410         d->noEnabled = enabled;
0411         d->authEnabled = enabled;
0412         d->yesEnabled = enabled;
0413     } else if (states & Auth) {
0414         d->authEnabled = enabled;
0415     } else if (states & No) {
0416         d->noEnabled = enabled;
0417     } else if (states & SelfBlocked) {
0418         d->selfBlockedEnabled = enabled;
0419     } else if (states & Yes) {
0420         d->yesEnabled = enabled;
0421     }
0422 
0423     d->updateAction();
0424 }
0425 
0426 bool Action::isEnabled(Action::State state) const
0427 {
0428     switch (state) {
0429         case Yes:
0430             return d->yesEnabled;
0431         case No:
0432             return d->noEnabled;
0433         case Auth:
0434             return d->authEnabled;
0435         case SelfBlocked:
0436             return d->selfBlockedEnabled;
0437         case None:
0438             return QAction::isEnabled();
0439         default:
0440             return false;
0441     }
0442 }
0443 
0444 void Action::setVisible(bool visible, States states)
0445 {
0446     if (states & All) {
0447         d->selfBlockedVisible = visible;
0448         d->noVisible = visible;
0449         d->authVisible = visible;
0450         d->yesVisible = visible;
0451     } else if (states & Auth) {
0452         d->authVisible = visible;
0453     } else if (states & No) {
0454         d->noVisible = visible;
0455     } else if (states & SelfBlocked) {
0456         d->selfBlockedVisible = visible;
0457     } else if (states & Yes) {
0458         d->yesVisible = visible;
0459     }
0460 
0461     d->updateAction();
0462 }
0463 
0464 bool Action::isVisible(Action::State state) const
0465 {
0466     switch (state) {
0467         case Yes:
0468             return d->yesVisible;
0469         case No:
0470             return d->noVisible;
0471         case Auth:
0472             return d->authVisible;
0473         case SelfBlocked:
0474             return d->selfBlockedVisible;
0475         case None:
0476             return QAction::isVisible();
0477         default:
0478             return false;
0479     }
0480 }
0481 
0482 void Action::setPolkitAction(const QString &actionId)
0483 {
0484     //TODO:
0485     d->actionId = actionId;
0486 
0487     d->computePkResult();
0488     d->updateAction();
0489 }
0490 
0491 //--------------------------------------------------
0492 
0493 QString Action::actionId() const
0494 {
0495     return d->actionId;
0496 }
0497 
0498 }
0499 
0500 }
0501 
0502 #include "moc_polkitqt1-gui-action.cpp"