File indexing completed on 2024-04-21 04:43:23
0001 // This is an example not a library 0002 /* 0003 SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com> 0004 SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "PkExample.h" 0010 0011 #include <polkitqt1-gui-actionbutton.h> 0012 #include <polkitqt1-gui-actionbuttons.h> 0013 #include <polkitqt1-authority.h> 0014 #include <QDebug> 0015 0016 #include <QDBusMessage> 0017 #include <QDBusConnection> 0018 0019 using namespace PolkitQt1; 0020 using namespace PolkitQt1::Gui; 0021 0022 PkExample::PkExample(QMainWindow *parent) 0023 : QMainWindow(parent) 0024 { 0025 setupUi(this); 0026 0027 ActionButton *bt; 0028 0029 // Here we create an ActionButton that is a subclass of Action 0030 // always pass a QAbstractButton pointer and action id 0031 // You can change the action id later if you want 0032 bt = new ActionButton(kickPB, "org.qt.policykit.examples.kick", this); 0033 // Here we are setting the text and icon to all four states 0034 // an action might have 0035 bt->setText("Kick!"); 0036 bt->setIcon(QPixmap(":/Icons/custom-no.png")); 0037 // By using set{Yes|No|Auth}Enabled you can set the states 0038 // when the button is enabled 0039 bt->setEnabled(true, Action::No); 0040 // As ActionButton is also an Action we cast it to add to menu 0041 menuActions->addAction(qobject_cast<Action *>(bt)); 0042 toolBar->addAction(qobject_cast<Action *>(bt)); 0043 // this signal is emitted when the user click on the action, 0044 // it will only happen if it was inserted in a QMenu or a QToolBar 0045 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0046 // This signal was propagated from the QAbstractButton just for 0047 // convenience in this case we don't have any benefit but the code 0048 // look cleaner 0049 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0050 // this is the Action activated signal, it is always emitted whenever 0051 // someone click and get authorized to do the action 0052 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0053 0054 bt = new ActionButton(cryPB, "org.qt.policykit.examples.cry", this); 0055 bt->setText("Cry!"); 0056 bt->setIcon(QPixmap(":/Icons/custom-yes.png")); 0057 menuActions->addAction(qobject_cast<Action *>(bt)); 0058 toolBar->addAction(qobject_cast<Action *>(bt)); 0059 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0060 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0061 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0062 0063 bt = new ActionButton(bleedPB, "org.qt.policykit.examples.bleed", this); 0064 bt->setText("Bleed!"); 0065 bt->setIcon(QPixmap(":/Icons/action-locked-default.png")); 0066 menuActions->addAction(qobject_cast<Action *>(bt)); 0067 toolBar->addAction(qobject_cast<Action *>(bt)); 0068 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0069 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0070 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0071 0072 // This action is more customized 0073 bt = new ActionButton(playPB, "org.qt.policykit.examples.play", this); 0074 bt->setText("Play!"); 0075 bt->setVisible(true, Action::No | Action::Auth | Action::Yes); 0076 bt->setEnabled(true, Action::No | Action::Auth | Action::Yes); 0077 // here we set the behavior of PolKitResul = No 0078 bt->setText("Can't play!", Action::No); 0079 bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No); 0080 bt->setToolTip("If your admin wasn't annoying, you could do this", Action::No); 0081 // here we set the behavior of PolKitResul = Auth 0082 bt->setText("Play?", Action::Auth); 0083 bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth); 0084 bt->setToolTip("Only card carrying tweakers can do this!", Action::Auth); 0085 // here we set the behavior of PolKitResul = Yes 0086 bt->setText("Play!", Action::Yes); 0087 bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes); 0088 bt->setToolTip("Go ahead, play!", Action::Yes); 0089 0090 menuActions->addAction(qobject_cast<Action *>(bt)); 0091 toolBar->addAction(qobject_cast<Action *>(bt)); 0092 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0093 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0094 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0095 0096 bt = new ActionButton(deletePB, "org.qt.policykit.examples.delete", this); 0097 bt->setText("Delete!"); 0098 bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No); 0099 bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth); 0100 bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes); 0101 menuActions->addAction(qobject_cast<Action *>(bt)); 0102 toolBar->addAction(qobject_cast<Action *>(bt)); 0103 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0104 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0105 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0106 0107 bt = new ActionButton(listenPB, "org.qt.policykit.examples.listen", this); 0108 bt->setText("Listen!"); 0109 bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No); 0110 bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth); 0111 bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes); 0112 menuActions->addAction(qobject_cast<Action *>(bt)); 0113 toolBar->addAction(qobject_cast<Action *>(bt)); 0114 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0115 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0116 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0117 0118 bt = new ActionButton(setPB, "org.qt.policykit.examples.set", this); 0119 bt->setText("Set!"); 0120 bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No); 0121 bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth); 0122 bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes); 0123 menuActions->addAction(qobject_cast<Action *>(bt)); 0124 toolBar->addAction(qobject_cast<Action *>(bt)); 0125 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0126 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0127 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0128 0129 bt = new ActionButton(shoutPB, "org.qt.policykit.examples.shout", this); 0130 bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No); 0131 bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth); 0132 bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes); 0133 bt->setText("Can't shout!", Action::No); 0134 bt->setText("Shout?", Action::Auth); 0135 bt->setText("Shout!", Action::Yes); 0136 menuActions->addAction(qobject_cast<Action *>(bt)); 0137 toolBar->addAction(qobject_cast<Action *>(bt)); 0138 connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction())); 0139 connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate())); 0140 connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); 0141 0142 // test configChanged 0143 } 0144 0145 PkExample::~PkExample() 0146 { 0147 } 0148 0149 void PkExample::activateAction() 0150 { 0151 // Here we cast the sender() to an Action and call activate() 0152 // on it. 0153 // Be careful in doing the same for ActionButton won't work as expected 0154 // as action->activate() is calling Action::activate() and 0155 // not ActionButton::activate which are different. 0156 // You can cast then to ActionButton but be careful 0157 // an Action casted to ActionButton may crash you app 0158 Action *action = qobject_cast<Action *>(sender()); 0159 // calling activate with winId() makes the auth dialog 0160 // be correct parented with your application. 0161 action->activate(); 0162 } 0163 0164 void PkExample::actionActivated() 0165 { 0166 // This slot is called whenever an action is allowed 0167 // here you will do your dirt job by calling a helper application 0168 // that might erase your hardrive ;) 0169 Action *action = qobject_cast<Action *>(sender()); 0170 0171 // this is our Special Action that after allowed will call the helper 0172 if (action->is("org.qt.policykit.examples.set")) { 0173 qDebug() << "toggled for: org.qt.policykit.examples.set"; 0174 0175 QDBusMessage message; 0176 message = QDBusMessage::createMethodCall("org.qt.policykit.examples", 0177 "/", 0178 "org.qt.policykit.examples", 0179 QLatin1String("set")); 0180 QList<QVariant> argumentList; 0181 argumentList << QVariant::fromValue(setCB->currentText()); 0182 message.setArguments(argumentList); 0183 // notice the systemBus here.. 0184 QDBusMessage reply = QDBusConnection::systemBus().call(message); 0185 if (reply.type() == QDBusMessage::ReplyMessage 0186 && reply.arguments().size() == 1) { 0187 // the reply can be anything, here we receive a bool 0188 QListWidgetItem *item; 0189 if (reply.arguments().first().toBool()) 0190 item = new QListWidgetItem(QPixmap(":/Icons/custom-yes.png"), 0191 QString("Implicit authorization for shout has been set to %0") 0192 .arg(setCB->currentText())); 0193 else 0194 item = new QListWidgetItem(QPixmap(":/Icons/custom-no.png"), 0195 QString("Can't change the implicit authorization. Denied.")); 0196 actionList->addItem(item); 0197 qDebug() << reply.arguments().first().toString(); 0198 } else if (reply.type() == QDBusMessage::MethodCallMessage) { 0199 qWarning() << "Message did not receive a reply (timeout by message bus)"; 0200 } 0201 return; 0202 } 0203 0204 // As debug message says we are pretending to be the mechanism for the 0205 // following action, here you will actually call your DBus helper that 0206 // will run as root (setuid is not needed, see DBus docs). 0207 // In the helper application you will issue checkAuthorizationSync, 0208 // passing the action id and the caller pid (which DBus will tell you). 0209 qDebug() << "pretending to be the mechanism for action:" << action->actionId(); 0210 0211 Authority::Result result; 0212 UnixProcessSubject subject(static_cast<uint>(QCoreApplication::applicationPid())); 0213 0214 result = Authority::instance()->checkAuthorizationSync(action->actionId(), subject, 0215 Authority::AllowUserInteraction); 0216 if (result == Authority::Yes) { 0217 // in the helper you will do the action 0218 qDebug() << "caller is authorized to do:" << action->actionId(); 0219 QListWidgetItem *item = new QListWidgetItem(QPixmap(":/Icons/custom-yes.png"), action->actionId()); 0220 actionList->addItem(item); 0221 } else { 0222 // OR return false to notify the caller that the action is not authorized. 0223 qDebug() << "caller is NOT authorized to do:" << action->actionId(); 0224 QListWidgetItem *item = new QListWidgetItem(QIcon(":/Icons/custom-no.png"), action->actionId()); 0225 actionList->addItem(item); 0226 } 0227 }