1 /*
2     SPDX-FileCopyrightText: 2009-2012 Dario Freddi <drf@kde.org>
3     SPDX-FileCopyrightText: 2008 Nicola Gigante <nicola.gigante@gmail.com>
4 
5     SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7 
8 #ifndef ACTION_H
9 #define ACTION_H
10 
11 #include <kauthcore_export.h>
12 
13 #include <QHash>
14 #include <QSharedDataPointer>
15 #include <QString>
16 #include <QVariant>
17 
18 namespace KAuth
19 {
20 class ExecuteJob;
21 
22 class ActionData;
23 /**
24  * @class Action kauthaction.h <KAuthAction>
25  *
26  * @brief Class to access, authorize and execute actions.
27  *
28  * This is the main class of the kauth API. It provides the interface to
29  * manipulate actions. Every action is identified by its name. Every instance
30  * of the Action class with the same name refers to the same action.
31  *
32  * Once you have an action object you can tell the helper to execute it
33  * (asking the user to authenticate if needed) with the execute() method.
34  * The simplest thing to do is to execute a single action synchronously
35  * blocking for the reply by callin exec() on the job object returned by
36  * execute().
37  *
38  * For asynchronous calls, use KAuth::ExecuteJob::start() instead.
39  * It sends the request
40  * to the helper and returns immediately. Before doing so you should however
41  * connect to at least the KJob::result(KJob *) signal to receive a slot call
42  * once the action is done executing.
43  *
44  * To use the execute() method you have to set the default helper's ID using
45  * the setHelperID() static method. Alternatively, you can specify the helperID using
46  * the overloaded version of the methods that takes it as a parameter.
47  *
48  * Each action object contains a QVariantMap object that is passed directly to the
49  * helper when the action is executed. You can access this map using the arguments()
50  * method. You can insert into it any kind of custom data you need to pass to the helper.
51  *
52  * @code
53  * void MyApp::runAction()
54  * {
55  *     action = KAuth::Action("org.kde.myapp.action");
56  *     KAuth::ExecuteJob *job = action.execute();
57  *     connect(job, &KAuth::ExecuteJob::result, this, &MyApp::actionResult);
58  *     job->start();
59  * }
60  *
61  * void MyApp::actionResult(KJob *kjob)
62  * {
63  *     auto job = qobject_cast<KAuth::ExecuteJob *>(kjob);
64  *     qDebug() << job.error() << job.data();
65  * }
66  * @endcode
67  *
68  * @since 4.4
69  */
70 class KAUTHCORE_EXPORT Action
71 {
72     Q_GADGET
73 public:
74     /**
75      * The three values set by authorization methods
76      */
77     enum AuthStatus {
78         DeniedStatus, ///< The authorization has been denied by the authorization backend
79         ErrorStatus, ///< An error occurred
80         InvalidStatus, ///< An invalid action cannot be authorized
81         AuthorizedStatus, ///< The authorization has been granted by the authorization backend
82         AuthRequiredStatus, ///< The user could obtain the authorization after authentication
83         UserCancelledStatus, ///< The user pressed Cancel the authentication dialog. Currently used only on the mac
84     };
85     Q_ENUM(AuthStatus)
86 
87     enum ExecutionMode {
88         ExecuteMode,
89         AuthorizeOnlyMode,
90     };
91     Q_ENUM(ExecutionMode)
92 
93     /**
94      * The backend specific details.
95      */
96     enum class AuthDetail {
97         DetailOther = 0,
98         DetailMessage, ///< The message to show in authentication dialog.
99     };
100     Q_ENUM(AuthDetail)
101 
102     /**
103      * Map of details.
104      */
105     typedef QMap<AuthDetail, QVariant> DetailsMap;
106 
107     /**
108      * @brief Default constructor
109      *
110      * This constructor sets the name to the empty string.
111      * Such an action is invalid and cannot be authorized nor executed, so
112      * you need to call setName() before you can use the object.
113      */
114     Action();
115 
116     /** Copy constructor */
117     Action(const Action &action);
118 
119     /**
120      * This creates a new action object with this name
121      * @param name The name of the new action
122      */
123     Action(const QString &name);
124 
125 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71)
126     /**
127      * This creates a new action object with this name and details
128      * @param name The name of the new action
129      * @param details The details of the action
130      *
131      * @see setDetails
132      * @deprecated since 5.68, use constructor with DetailsMap
133      */
134     KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use constructor with DetailsMap")
135     Action(const QString &name, const QString &details);
136 #endif
137 
138     /**
139      * This creates a new action object with this name and details
140      * @param name The name of the new action
141      * @param details The details of the action
142      *
143      * @see setDetails
144      * @since 5.68
145      */
146     Action(const QString &name, const DetailsMap &details);
147 
148     /// Virtual destructor
149     ~Action();
150 
151     /// Assignment operator
152     Action &operator=(const Action &action);
153 
154     /**
155      * @brief Comparison operator
156      *
157      * This comparison operator compares the <b>names</b> of two
158      * actions and returns whether they are the same. It does not
159      * care about the arguments stored in the actions. However,
160      * if two actions are invalid they'll match as equal, even
161      * if the invalid names are different.
162      *
163      * @returns true if the two actions are the same or both invalid
164      */
165     bool operator==(const Action &action) const;
166 
167     /**
168      * @brief Negated comparison operator
169      *
170      * Returns the negation of operator==
171      *
172      * @returns true if the two actions are different and not both invalid
173      */
174     bool operator!=(const Action &action) const;
175 
176     /**
177      * @brief Gets the action's name.
178      *
179      * This is the unique attribute that identifies
180      * an action object. Two action objects with the same
181      * name always refer to the same action.
182      *
183      * @return The action name
184      */
185     QString name() const;
186 
187     /**
188      * @brief Sets the action's name.
189      *
190      * It's not common to change the action name
191      * after its creation. Usually you set the name
192      * with the constructor (and you have to, because
193      * there's no default constructor)
194      */
195     void setName(const QString &name);
196 
197     /**
198      * @brief Gets the action's timeout.
199      *
200      * The timeout of the action in milliseconds
201      * -1 means the default D-Bus timeout (usually 25 seconds)
202      *
203      * @since 5.29
204      *
205      * @return The action timeouts
206      */
207     int timeout() const;
208 
209     /**
210      * @brief Sets the action's timeout.
211      *
212      * The timeout of the action in milliseconds
213      * -1 means the default D-Bus timeout (usually 25 seconds)
214      *
215      * @since 5.29
216      *
217      */
218     void setTimeout(int timeout);
219 
220 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71)
221     /**
222      * @brief Sets the action's details
223      *
224      * You can use this function to provide the user more details
225      * (if the backend supports it) on the action being authorized in
226      * the authorization dialog
227      *
228      * @deprecated since 5.68, use setDetailsV2() with DetailsMap.
229      */
230     KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use setDetailsV2() with DetailsMap")
231     void setDetails(const QString &details);
232 #endif
233 
234     /**
235      * @brief Sets the action's details
236      *
237      * You can use this function to provide the user more details
238      * (if the backend supports it) on the action being authorized in
239      * the authorization dialog
240      *
241      * @param details the details describing the action. For e.g, "DetailMessage" key can
242      * be used to give a customized authentication message.
243      *
244      * @since 5.68
245      */
246     void setDetailsV2(const DetailsMap &details);
247 
248 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71)
249     /**
250      * @brief Gets the action's details
251      *
252      * The details that will be shown in the authorization dialog, if the
253      * backend supports it.
254      *
255      * @return The action's details
256      * @deprecated since 5.68, use detailsV2() with DetailsMap.
257      */
258     KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use detailsV2() with DetailsMap")
259     QString details() const;
260 #endif
261 
262     /**
263      * @brief Gets the action's details
264      *
265      * The details that will be shown in the authorization dialog, if the
266      * backend supports it.
267      *
268      * @return The action's details
269      * @since 5.68
270      */
271     DetailsMap detailsV2() const;
272 
273     /**
274      * @brief Returns if the object represents a valid action
275      *
276      * Action names have to respect a simple syntax.
277      * They have to be all in lowercase characters, separated
278      * by dots. Dots can't appear at the beginning and at the end of
279      * the name.
280      *
281      * In other words, the action name has to match this perl-like
282      * regular expression:
283      * @verbatim
284      * /^[a-z]+(\.[a-z]+)*$/
285      * @endverbatim
286      *
287      * This method returns false if the action name doesn't match the
288      * valid syntax.
289      *
290      * If the backend supports it, this method also checks if the action is
291      * valid and recognized by the backend itself.
292      * @note This may spawn a nested event loop.
293      *
294      * Invalid actions cannot be authorized nor executed.
295      * The empty string is not a valid action name, so the default
296      * constructor returns an invalid action.
297      */
298     bool isValid() const;
299 
300     /**
301      * @brief Gets the default helper ID used for actions execution
302      *
303      * The helper ID is the string that uniquely identifies the helper in
304      * the system. It is the string passed to the KAUTH_HELPER() macro
305      * in the helper source. Because one could have different helpers,
306      * you need to specify an helper ID for each execution, or set a default
307      * ID by calling setHelperID(). This method returns the current default
308      * value.
309      *
310      * @return The default helper ID.
311      */
312     QString helperId() const;
313 
314     /**
315      * @brief Sets the default helper ID used for actions execution
316      *
317      * This method sets the helper ID which contains the body of this action.
318      * If the string is non-empty, the corresponding helper will be fired and
319      * the action executed inside the helper. Otherwise, the action will be just
320      * authorized.
321      *
322      * @note To unset a previously set helper, just pass an empty string
323      *
324      * @param id The default helper ID.
325      *
326      * @see hasHelper
327      * @see helperId
328      */
329     void setHelperId(const QString &id);
330 
331     /**
332      * @brief Checks if the action has an helper
333      *
334      * This function can be used to check if an helper will be called upon the
335      * execution of an action. Such an helper can be set through setHelperID. If
336      * this function returns false, upon execution the action will be just authorized.
337      *
338      * @since 4.5
339      *
340      * @return Whether the action has an helper or not
341      *
342      * @see setHelperID
343      */
344     bool hasHelper() const;
345 
346     /**
347      * @brief Sets the map object used to pass arguments to the helper.
348      *
349      * This method sets the variant map that the application
350      * can use to pass arbitrary data to the helper when executing the action.
351      *
352      * Only non-gui variants are supported.
353      *
354      * @param arguments The new arguments map
355      */
356     void setArguments(const QVariantMap &arguments);
357 
358     /**
359      * @brief Returns map object used to pass arguments to the helper.
360      *
361      * This method returns the variant map that the application
362      * can use to pass arbitrary data to the helper when executing the action.
363      *
364      * @return The arguments map that will be passed to the helper.
365      */
366     QVariantMap arguments() const;
367 
368     /**
369      * @brief Convenience method to add an argument.
370      *
371      * This method adds the pair @c key/value to the QVariantMap used to
372      * send custom data to the helper.
373      *
374      * Use this method if you don't want to create a new QVariantMap only to
375      * add a new entry.
376      *
377      * @param key The new entry's key
378      * @param value The value of the new entry
379      */
380     void addArgument(const QString &key, const QVariant &value);
381 
382     /**
383      * @brief Gets information about the authorization status of an action
384      *
385      * This methods query the authorization backend to know if the user can try
386      * to acquire the authorization for this action. If the result is Action::AuthRequired,
387      * the user can try to acquire the authorization by authenticating.
388      *
389      * It should not be needed to call this method directly, because the execution methods
390      * already take care of all the authorization stuff.
391      *
392      * @return @c Action::Denied if the user doesn't have the authorization to execute the action,
393      *         @c Action::Authorized if the action can be executed,
394      *         @c Action::AuthRequired if the user could acquire the authorization after authentication,
395      *         @c Action::UserCancelled if the user cancels the authentication dialog. Not currently supported by the Polkit backend
396      */
397     AuthStatus status() const;
398 
399     /**
400      * @brief Get the job object used to execute the action
401      *
402      * @return The KJob::ExecuteJob object to be used to run the action.
403      */
404     ExecuteJob *execute(ExecutionMode mode = ExecuteMode);
405 
406     /**
407      * @brief Sets a parent widget for the authentication dialog
408      *
409      * This function is used for explicitly setting a parent window for an eventual authentication dialog required when
410      * authorization is triggered. Some backends, in fact, (like polkit-1) need to have a parent explicitly set for displaying
411      * the dialog correctly.
412      *
413      * @note If you are using KAuth through one of KDE's GUI components (KPushButton, KCModule...) you do not need and should not
414      *       call this function, as it is already done by the component itself.
415      *
416      * @since 4.6
417      *
418      * @param parent A QWidget which will be used as the dialog's parent
419      */
420     void setParentWidget(QWidget *parent);
421 
422     /**
423      * @brief Returns the parent widget for the authentication dialog for this action
424      *
425      * @since 4.6
426      *
427      * @returns A QWidget which will is being used as the dialog's parent
428      */
429     QWidget *parentWidget() const;
430 
431 private:
432     QSharedDataPointer<ActionData> d;
433 };
434 
435 } // namespace Auth
436 
437 #endif
438