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