// This is an example not a library /*************************************************************************** * Copyright (C) 2009 Radek Novacek * * Copyright (C) 2008 Daniel Nicoletti * * * * 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 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 "PkExample.h" #include "gui/polkit-tqt-gui-actionbutton.h" #include "gui/polkit-tqt-gui-actionbuttons.h" #include "core/polkit-tqt-authority.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PolkitTQt; using namespace PolkitTQt::Gui; PkExample::PkExample() : TQMainWindow(nullptr, "Polkit tqt example application", WDestructiveClose) { TQWidget *privateLayoutWidget = new TQWidget(this, "qt_central_widget"); setCentralWidget(privateLayoutWidget); grid = new TQGridLayout(nullptr, 9, 1, 0, 6, "grid"); grid->setColSpacing(0, 700); grid->setColSpacing(1, 200); kickL = new TQLabel(privateLayoutWidget, "kickL"); kickPB = new TQPushButton(privateLayoutWidget, "kickPB"); grid->addWidget(kickL, 0, 0); grid->addWidget(kickPB, 0, 1); cryL = new TQLabel(privateLayoutWidget, "cryL"); cryPB = new TQPushButton(privateLayoutWidget, "cryPB"); grid->addWidget(cryL, 1, 0); grid->addWidget(cryPB, 1, 1); bleedL = new TQLabel(privateLayoutWidget, "bleedL"); bleedPB = new TQPushButton(privateLayoutWidget, "bleedPB"); grid->addWidget(bleedL, 2, 0); grid->addWidget(bleedPB, 2, 1); playL = new TQLabel(privateLayoutWidget, "playL"); playPB = new TQPushButton(privateLayoutWidget, "playPB"); grid->addWidget(playL, 3, 0); grid->addWidget(playPB, 3, 1); listenL = new TQLabel(privateLayoutWidget, "listenL"); listenPB = new TQPushButton(privateLayoutWidget, "listenPB"); grid->addWidget(listenL, 4, 0); grid->addWidget(listenPB, 4, 1); deleteL = new TQLabel(privateLayoutWidget, "deleteL"); deletePB = new TQPushButton(privateLayoutWidget, "deletePB"); grid->addWidget(deleteL, 5, 0); grid->addWidget(deletePB, 5, 1); deleteL_2 = new TQLabel(privateLayoutWidget, "deleteL_2"); setCB = new TQComboBox(FALSE, privateLayoutWidget, "setCB"); grid->addMultiCellWidget(deleteL_2, 6, 7, 0, 0); grid->addWidget(setCB, 6, 1); setPB = new TQPushButton(privateLayoutWidget, "setPB"); deleteL_3 = new TQLabel(privateLayoutWidget, "deleteL_3"); grid->addWidget(setPB, 7, 1); grid->addWidget(deleteL_3, 8, 0); shoutPB = new TQPushButton(privateLayoutWidget, "shoutPB"); grid->addWidget(shoutPB, 8, 1); vLayout = new TQVBoxLayout(privateLayoutWidget, 11, 6, "vLayout"); vLayout->addLayout(grid); actionList = new TQListView(privateLayoutWidget); actionList->addColumn("Action"); actionList->addColumn("Result"); actionList->setSorting(-1); vLayout->addWidget(actionList); // menubar menubar = new TQMenuBar(this, "menubar"); menubar->setGeometry(TQRect(0, 0, 800, 22)); menuActions = new TQPopupMenu(this); menubar->insertItem(TQString(""), menuActions, 2); // toolbars toolBar = new TQToolBar(TQString(""), this, DockTop); // statusbar statusBar(); languageChange(); resize(TQSize(900, 700).expandedTo(minimumSizeHint())); clearWState(WState_Polished); // Setup actions ActionButton *bt; // Here we create an ActionButton that is a subclass of Action // always pass a TQButton pointer and action id // You can change the action id later if you want bt = new ActionButton(kickPB, "org.tqt.policykit.examples.kick", this); // Here we are setting the text and icon to all four states // an action might have bt->setText("Kick!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png")); // By using set{Yes|No|Auth}Enabled you can set the states // when the button is enabled bt->setEnabled(true, Action::No); // As ActionButton is also an Action we cast it to add to menu ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); // this signal is emitted when the user click on the action, // it will only happen if it was inserted in a TQMenu or a TQToolBar connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); // This signal was propagated from the TQButton just for // convenience in this case we don't have any benefit but the code // look cleaner connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); // this is the Action activated signal, it is always emmited whenever // someone click and get authorized to do the action connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(cryPB, "org.tqt.policykit.examples.cry", this); bt->setText("Cry!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png")); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(bleedPB, "org.tqt.policykit.examples.bleed", this); bt->setText("Bleed!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png")); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); // This action is more customized bt = new ActionButton(playPB, "org.tqt.policykit.examples.play", this); bt->setText("Play!"); bt->setVisible(true, (Action::States)(Action::No | Action::Auth | Action::Yes)); bt->setEnabled(true, (Action::States)(Action::No | Action::Auth | Action::Yes)); // here we set the behavior of PolKitResult = No bt->setText("Can't play!", Action::No); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No); bt->setToolTip("If your admin wasn't annoying, you could do this", Action::No); // here we set the behavior of PolKitResult = Auth bt->setText("Play?", Action::Auth); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth); bt->setToolTip("Only card carrying tweakers can do this!", Action::Auth); // here we set the behavior of PolKitResult = Yes bt->setText("Play!", Action::Yes); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes); bt->setToolTip("Go ahead, play!", Action::Yes); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(listenPB, "org.tqt.policykit.examples.listen", this); bt->setText("Listen!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(deletePB, "org.tqt.policykit.examples.delete", this); bt->setText("Delete!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(setPB, "org.tqt.policykit.examples.set", this); bt->setText("Set!"); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); bt = new ActionButton(shoutPB, "org.tqt.policykit.examples.shout", this); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png"), Action::No); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/action-locked-default.png"), Action::Auth); bt->setIconSet(TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png"), Action::Yes); bt->setText("Can't shout!", Action::No); bt->setText("Shout?", Action::Auth); bt->setText("Shout!", Action::Yes); ::tqt_cast(bt)->addTo(menuActions); ::tqt_cast(bt)->addTo(toolBar); connect(bt, SIGNAL(activated()), this, SLOT(activateAction())); connect(bt, SIGNAL(clicked(TQButton*, bool)), bt, SLOT(activate())); connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated())); } void PkExample::languageChange() { setCaption(tr("PolicyKit-tqt example")); kickL->setText(tr("Making the helper Kick is not allowed. Action cannot be activated.")); kickPB->setText(tr("Kick!")); cryL->setText(tr("Making the helper Cry is always allowed. Action can be activated without authentication.")); cryPB->setText(tr("Cry!")); bleedL->setText(tr("Making the helper Bleed requires the user to authenticate. This is a one-shot authorization.")); bleedPB->setText(tr("Bleed!")); playL->setText(tr("Making the helper Play requires a system administrator to authenticate. This is a one-shot authorization.")); playPB->setText(tr("Play!")); listenL->setText(tr("Making the helper Listen requires the user to authenticate. The authorization will be kept for a brief period.")); listenPB->setText(tr("Listen!")); deleteL->setText(tr("Making the helper Delete requires a system administrator to authenticate. The authorization will be kept for a brief period.")); deletePB->setText(tr("Delete!")); deleteL_2->setText(tr("Set is special action. It sets the permissions for the Shout action by actually using the helper application to change the implicit authorization.")); setCB->clear(); setCB->insertItem(tr("no")); setCB->insertItem(tr("yes")); setCB->insertItem(tr("auth_self")); setCB->insertItem(tr("auth_admin")); setCB->insertItem(tr("auth_self_keep")); setCB->insertItem(tr("auth_admin_keep")); setPB->setText(tr("Set!")); deleteL_3->setText(tr("The implicit authorization for the Shout action is set by the Set action. You can watch how different options can change behaviour of this action.")); shoutPB->setText(tr("Shout!")); toolBar->setCaption(tr("toolBar")); if (menubar->findItem(2)) { menubar->findItem(2)->setText(tr("&Actions")); } } void PkExample::activateAction() { // Here we cast the sender() to an Action and call activate() on it. // Be careful in doing the same for ActionButton won't work as expected // as action->activate() is calling Action::activate() and // not ActionButton::activate which are different. // You can cast then to ActionButton but be carefull // an Action casted to ActionButton may crash you app Action *action = ::tqt_cast(sender()); // calling activate with winId() makes the auth dialog // be correct parented with your application. action->activate(); } void PkExample::actionActivated() { // This slot is called whenever an action is allowed // here you will do your dirt job by calling a helper application // that might erase your hardrive ;) Action *action = ::tqt_cast(sender()); // this is our Special Action that after allowed will call the helper if (action->is("org.tqt.policykit.examples.set")) { tqDebug("toggled for: org.tqt.policykit.examples.set"); TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus); TQT_DBusProxy exampleProxy("org.tqt.policykit.examples", "/", "org.tqt.policykit.examples", dbusConn); TQT_DBusError error; TQValueList params; params << TQT_DBusData::fromString(setCB->currentText()); TQT_DBusMessage reply = exampleProxy.sendWithReply("set", params, &error); if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) { // the reply can be anything, here we receive a bool TQListViewItem *item; if (reply[0].toBool()) { item = new TQListViewItem(actionList); item->setText(0, TQString("Implicit authorization for shout has been set to ") + setCB->currentText()); item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png")); } else { item = new TQListViewItem(actionList); item->setText(0, TQString("Can't change the implicit authorization. Denied.")); item->setPixmap(1, TQPixmap("/usr/share/apps/icons/custom-no.png")); } actionList->insertItem(item); } else if (reply.type() == TQT_DBusMessage::MethodCallMessage) { tqDebug("Message did not receive a reply (timeout by message bus)"); } return; } // As debug message says we are pretending to be the mechanism for the // following action, here you will actually call your DBus helper that // will run as root (setuid is not needed, see DBus docs). // In the helper application you will issue checkAuthorizationSync, // passing the action id and the caller pid (which DBus will tell you). tqDebug(TQString("Pretending to be the mechanism for action %1").arg(action->actionId())); Authority::Result result; UnixProcessSubject subject(static_cast(getpid())); result = Authority::instance()->checkAuthorizationSync(action->actionId(), subject, Authority::AllowUserInteraction); TQListViewItem *item; item = new TQListViewItem(actionList); item->setText(0, action->actionId()); if (result == Authority::Yes) { // in the helper you will do the action tqDebug(TQString("caller is authorized to do: %1").arg(action->actionId())); item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-yes.png")); } else { // or return false to notify the caller that the action is not authorized. tqDebug(TQString("caller is NOT authorized to do: %1").arg(action->actionId())); item->setPixmap(1, TQPixmap("/usr/share/apps/polkit-tqt/icons/custom-no.png")); } actionList->insertItem(item); } #include "PkExample.moc"