kdelibs/kdecore/auth/kauthaction.h

507 lines
20 KiB
C
Raw Normal View History

2014-11-13 01:04:59 +02:00
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser 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 .
*/
#ifndef ACTION_H
#define ACTION_H
#include <QtCore/QString>
#include <QtCore/QVariant>
#include <QtCore/QHash>
#include <kdecore_export.h>
#include "kauthactionreply.h"
namespace KAuth
{
class ActionWatcher;
/**
* @brief Class to access, authorize and execute actions.
*
* This is the main class of the kauth API. It provides the interface to
* manipulate actions. Every action is identified by its name. Every instance
* of the Action class with the same name refers to the same action.
*
* Once you have an action object you can tell the helper to execute it
* (asking the user to authenticate if needed) with one of the execute*() methods.
* The simplest thing to do is to execute a single action synchronously
* blocking for the reply, using the execute() method.
*
* For asynchronous calls, use the executeAsync() method. It sends the request
* to the helper and returns immediately. You can optionally provide an object
* and a slot. This will be connected to the actionPerformed() signal of the
* action's ActionWatcher object.
* By calling the watcher() method, you obtain an object that emits some useful
* signals that you can receive while the action is in progress. Those signals
* are emitted also with the synchronous calls.
* To execute a bunch of actions with a single call, you can use the executeActions()
* static method. This is not the same as calling executeAsync() for each action,
* because the actions are execute with a single request to the helper.
* To use any of the execute*() methods you have to set the default helper's ID using
* the setHelperID() static method. Alternatively, you can specify the helperID using
* the overloaded version of the methods that takes it as a parameter.
*
* Each action object contains a QVariantMap object that is passed directly to the
* helper when the action is executed. You can access this map using the arguments()
* method. You can insert into it any kind of custom data you need to pass to the helper.
*
* @since 4.4
*/
class KDECORE_EXPORT Action
{
class Private;
Private * const d;
public:
/**
* The three values returned by authorization methods
*/
enum AuthStatus {
Denied, ///< The authorization has been denied by the authorization backend
Error, ///< An error occurred
Invalid, ///< An invalid action cannot be authorized
Authorized, ///< The authorization has been granted by the authorization backend
AuthRequired, ///< The user could obtain the authorization after authentication
UserCancelled ///< The user pressed Cancel the authentication dialog. Currently used only on the mac
};
/**
* @brief Default constructor
*
* This constructor sets the name to the empty string.
* Such an action is invalid and cannot be authorized nor executed, so
* you need to call setName() before you can use the object.
*/
Action();
/** Copy constructor */
Action(const Action &action);
/**
* This creates a new action object with this name
* @param name The name of the new action
*/
Action(const QString &name);
/**
* This creates a new action object with this name and details
* @param name The name of the new action
* @param details The details of the action
*
* @see setDetails
*/
Action(const QString &name, const QString &details);
/// Virtual destructor
~Action();
/// Assignment operator
Action &operator=(const Action &action);
/**
* @brief Comparison operator
*
* This comparison operator compares the <b>names</b> of two
* actions and returns whether they are the same. It does not
* care about the arguments stored in the actions. However,
* if two actions are invalid they'll match as equal, even
* if the invalid names are different.
*
* @returns true if the two actions are the same or both invalid
*/
bool operator==(const Action &action) const;
/**
* @brief Negated comparison operator
*
* Returns the negation of operator==
*
* @returns true if the two actions are different and not both invalid
*/
bool operator!=(const Action &action) const;
/**
* @brief Gets the action's name.
*
* This is the unique attribute that identifies
* an action object. Two action objects with the same
* name always refer to the same action.
*
* @return The action name
*/
QString name() const;
/**
* @brief Sets the action's name.
*
* It's not common to change the action name
* after its creation. Usually you set the name
* with the constructor (and you have to, because
* there's no default constructor)
*/
void setName(const QString &name);
/**
* @brief Sets the action's details
*
* You can use this function to provide the user more details
* (if the backend supports it) on the action being authorized in
* the authorization dialog
*/
void setDetails(const QString &details);
/**
* @brief Gets the action's details
*
* The details that will be shown in the authorization dialog, if the
* backend supports it.
*
* @return The action's details
*/
QString details() const;
/**
* @brief Returns if the object represents a valid action
*
* Action names have to respect a simple syntax.
* They have to be all in lowercase characters, separated
* by dots. Dots can't appear at the beginning and at the end of
* the name.
*
* In other words, the action name has to match this perl-like
* regular expression:
* @verbatim
* /^[a-z]+(\.[a-z]+)*$/
* @endverbatim
*
* This method returns false if the action name doesn't match the
* valid syntax.
*
* If the backend supports it, this method also checks if the action is
* valid and recognized by the backend itself.
*
* Invalid actions cannot be authorized nor executed.
* The empty string is not a valid action name, so the default
* constructor returns an invalid action.
*/
bool isValid() const;
/**
* @brief Gets the default helper ID used for actions execution
*
* The helper ID is the string that uniquely identifies the helper in
* the system. It is the string passed to the KDE4_AUTH_HELPER() macro
* in the helper source. Because one could have different helpers,
* you need to specify an helper ID for each execution, or set a default
* ID by calling setHelperID(). This method returns the current default
* value.
*
* @return The default helper ID.
*/
QString helperID() const;
/**
* @brief Sets the default helper ID used for actions execution
*
* This method sets the helper ID which contains the body of this action.
* If the string is non-empty, the corresponding helper will be fired and
* the action executed inside the helper. Otherwise, the action will be just
* authorized.
*
* @note To unset a previously set helper, just pass an empty string
*
* @param id The default helper ID.
*
* @see hasHelper
* @see helperID
*/
void setHelperID(const QString &id);
/**
* @brief Checks if the action has an helper
*
* This function can be used to check if an helper will be called upon the
* execution of an action. Such an helper can be set through setHelperID. If
* this function returns false, upon execution the action will be just authorized.
*
* @since 4.5
*
* @return Whether the action has an helper or not
*
* @see setHelperID
*/
bool hasHelper() const;
/**
* @brief Gets the ActionWatcher object for this action
*
* ActionWatcher objects are used to get notifications about the action
* execution status. Every action watcher is tied to an action and
* every action has a watcher. This means that if you call this method
* on two different Action objects with the same name, you'll get the
* same watcher object.
*
* @return The action watcher for this action
*/
ActionWatcher *watcher();
/**
* @brief Sets the map object used to pass arguments to the helper.
*
* This method sets the variant map that the application
* can use to pass arbitrary data to the helper when executing the action.
*
* @param arguments The new arguments map
*/
void setArguments(const QVariantMap &arguments);
/**
* @brief Returns map object used to pass arguments to the helper.
*
* This method returns the variant map that the application
* can use to pass arbitrary data to the helper when executing the action.
*
* @return The arguments map that will be passed to the helper.
*/
QVariantMap arguments() const;
/**
* @brief Convenience method to add an argument.
*
* This method adds the pair @c key/value to the QVariantMap used to
* send custom data to the helper.
*
* Use this method if you don't want to create a new QVariantMap only to
* add a new entry.
*
* @param key The new entry's key
* @param value The value of the new entry
*/
void addArgument(const QString &key, const QVariant &value);
/**
* @brief Acquires authorization for an action without excuting it.
*
* @note Please use this method if you really know what you are doing. If you are
* implementing a GUI, you probably should look into earlyAuthorize instead.
*
* @note Please remember that calling this method is not required for a successful action
* execution: it is safe and advised to call execute() only, without a previous call
* to authorize or earlyAuthorize.
*
* This method acquires the authorization rights for the action, asking
* the user to authenticate if needed. It tries very hard to resolve a possible
* challenge (AuthRequired); for this reason, it is meant only for advanced usages.
* If you are unsure, always use earlyAuthorize or execute the action directly.
*
* @return The result of the authorization process
*
* @see earlyAuthorize
*/
AuthStatus authorize() const;
/**
* @brief Tries to resolve authorization status in the best possible way without executing the action
*
* This method checks for the status of the action, and tries to acquire authorization
* (if needed) if the backend being used supports client-side authorization.
*
* This means this method is not reliable - its purpose is to provide user interfaces with
* an efficient means to acquire authorization as early as possible, without interrupting
* the user's workflow. If the backend's authentication phase happens in the helper and the
* action requires authentication, \c Authorized will be returned.
*
* The main difference with authorize is that this method does not try to acquire authorization
* if the backend's authentication phase happens in the helper: using authorize in such a case
* might lead to ask the user its password twice, as the helper might time out, or in the case
* of a one shot authorization, the scope of the authorization would end with the authorization
* check itself. For this reason, you should @b always use this method instead of authorize, which
* is meant only for very advanced usages.
*
* This method is always safe to be called and used before an execution, even if not needed.
*
* @since 4.5
*
* @return The result of the early authorization process, with the caveats described above.
*/
AuthStatus earlyAuthorize() const;
/**
* @brief Gets information about the authorization status of an action
*
* This methods query the authorization backend to know if the user can try
* to acquire the authorization for this action. If the result is Action::AuthRequired,
* the user can try to acquire the authorization by authenticating.
*
* It should not be needed to call this method directly, because the execution methods
* already take care of all the authorization stuff.
*
* @return @c Action::Denied if the user doesn't have the authorization to execute the action,
* @c Action::Authorized if the action can be executed,
* @c Action::AuthRequired if the user could acquire the authorization after authentication,
* @c Action::UserCancelled if the user cancels the authentication dialog. Not currently supported by the Polkit backend
*/
AuthStatus status() const;
/**
* @brief Synchronously executes the action
*
* This is the simpler of all the action execution methods. It sends an execution request to the
* caller, and returns the reply directly to the caller. The ActionReply object will contain the
* custom data coming from the helper.
*
* The method blocks the execution, and will
* return only when the action has been completed (or failed). Take note, however, that with the D-Bus
* helper proxy (currently the only one implemented on all the supported platforms), the request is
* sent using the QDBus::BlockWithGui flag.
*
* This means the method will enter a local eventloop to wait
* for the reply. This allows the application GUI to stay responsive, but you have to be prepared to
* receive other events in the meantime.
*
* All the signals from the ActionWatcher class are emitted also with this method (although they're more
* useful with the asynchronous calls)
*
* The method checks for authorization before to execute the action. If the user is not authorized, the
* return value will be ActionReply::AuthorizationDeniedReply.
* If the user cancels the authentication, the return value should be ActionReply::UserCancelledReply.
* Due to policykit limitations, this currently only with the Mac OS X backend.
*
* If the helper is busy executing another action (or action group) the reply will be ActionReply::HelperBusyReply
*
* If the request cannot be sent for bus errors, the method returns ActionReply::DBusErrorReply.
*
* @return The reply from the helper, or an error reply if something's wrong.
*/
ActionReply execute() const;
/**
* @brief Synchronously executes the action with a specific helperID
*
* This method does the exact same thing as execute(), but it takes a specific helperID, useful
* if you don't want to use the default one without changing it with setHelperID()
*
* @param helperID The helper ID to use for the execution of this action
* @return The reply from the helper, or an error if something's wrong.
*/
ActionReply execute(const QString &helperID) const;
void setExecutesAsync(bool async);
bool executesAsync() const;
/**
* @brief Asynchronously executes a group of actions with a single request
*
* This method executes each action in the list. It checks for authorization of each action, and put the
* denied actions, if any, in the list pointed by the deniedActions parameter, if not NULL.
*
* Please note that with the D-Bus helper proxy (currently the only one implemented), the execution of a group
* of actions is very different from executing in sequence each action using, for example, executeAsync().
* Currently, the helper can execute only one request at the time. For this reason, if you have to call
* different actions in sequence, you can't call executeAsync() like this:
* @code
* action1.executeAsync();
* action2.executeAsync();
* @endcode
* because the second call will almost certainly return ActionReply::HelperBusy. You would have to execute the second
* action in the slot connected to the first action's actionPerformed() signal. This is not so good. This method
* allows the application to send a request with a list of actions. With this method, the code above becomes:
* @code
* QList<Action> list;
* list << action1 << action2;
* Action::executeActions(list);
* @endcode
* The return value will be false if communication errors occur. It will also be false if <b>all</b> the actions
* in the list are denied.
*
* @param actions The list of actions to execute
* @param deniedActions A pointer to a list to fill with the denied actions. Pass NULL if you don't need them.
* @param helperId The helper ID to execute the actions on.
*/
static bool executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId);
/**
* Convenience overload. This overload lets you specify, in addition, a QWidget which will be used as the
* authentication dialog's parent.
*
* @since 4.6
*
* @see executeActions
* @see setParentWidget
*/
static bool executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId,
QWidget *parent);
/**
* @brief Ask the helper to stop executing an action
*
* This method sends a request to the helper asking to stop the execution of an action. It is only
* useful for long-running actions, because short and fast actions won't obbey to this request most of the times.
* Calling this method will make the HelperSupport::isStopped() method to return true the next time it's called.
*
* It's the helper's responsibility to regularly call it and exit if requested
* The actionPerformed() signal is emitted normally because, actually, the helper exists regularly. The return data
* in this case is application-dependent.
*/
void stop();
/**
* @brief Ask the helper to stop executing an action, using a specific helper ID
*
* This method works exactly as the stop() method, but it lets you specify an helper ID different from the
* default one.
*
* To stop an action you need to send the stop request to the helper that is executing that action. This of course means you have to
* use the same helperID used for the execution call (either passed as a parameter or set as default with setHelperID() )
*/
void stop(const QString &helperID);
/**
* @brief Sets a parent widget for the authentication dialog
*
* This function is used for explicitly setting a parent window for an eventual authentication dialog required when
* authorization is triggered. Some backends, in fact, (like polkit-1) need to have a parent explicitly set for displaying
* the dialog correctly.
*
* @note If you are using KAuth through one of KDE's GUI components (KPushButton, KCModule...) you do not need and should not
* call this function, as it is already done by the component itself.
*
* @since 4.6
*
* @param parent A QWidget which will be used as the dialog's parent
*/
void setParentWidget(QWidget *parent);
/**
* @brief Returns the parent widget for the authentication dialog for this action
*
* @since 4.6
*
* @returns A QWidget which will is being used as the dialog's parent
*/
QWidget *parentWidget() const;
};
} // namespace Auth
#endif