File indexing completed on 2025-04-20 12:19:12
0001 /* 0002 SPDX-FileCopyrightText: 2009-2012 Dario Freddi <drf@kde.org> 0003 SPDX-FileCopyrightText: 2008 Nicola Gigante <nicola.gigante@gmail.com> 0004 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #ifndef KAUTH_ACTION_H 0010 #define KAUTH_ACTION_H 0011 0012 #include "kauthcore_export.h" 0013 0014 #include <QHash> 0015 #include <QSharedDataPointer> 0016 #include <QString> 0017 #include <QVariant> 0018 0019 #if __has_include(<chrono>) 0020 #include <chrono> 0021 #endif 0022 0023 namespace KAuth 0024 { 0025 class ExecuteJob; 0026 0027 class ActionData; 0028 /** 0029 * @class Action action.h <KAuth/Action> 0030 * 0031 * @brief Class to access, authorize and execute actions. 0032 * 0033 * This is the main class of the KAuth API. It provides the interface to 0034 * manipulate actions. Every action is identified by its name. Every instance 0035 * of the Action class with the same name refers to the same action. 0036 * 0037 * Once you have an action object you can tell the helper to execute it 0038 * (asking the user to authenticate if needed) with the execute() method. 0039 * The simplest thing to do is to execute a single action synchronously 0040 * blocking for the reply by calling KJob::exec() on the job object returned by 0041 * execute(). 0042 * 0043 * For asynchronous calls, use KAuth::ExecuteJob::start() instead. 0044 * It sends the request 0045 * to the helper and returns immediately. Before doing so you should however 0046 * connect to at least the KJob::result(KJob *) signal to receive a slot call 0047 * once the action is done executing. 0048 * 0049 * To use the execute() method you have to set the default helper's ID using 0050 * the setHelperId() static method. Alternatively, you can specify the helperID using 0051 * the overloaded version of the methods that takes it as a parameter. 0052 * 0053 * Each action object contains a QVariantMap object that is passed directly to the 0054 * helper when the action is executed. You can access this map using the arguments() 0055 * method. You can insert into it any kind of custom data you need to pass to the helper. 0056 * 0057 * @code 0058 * void MyApp::runAction() 0059 * { 0060 * action = KAuth::Action("org.kde.myapp.action"); 0061 * KAuth::ExecuteJob *job = action.execute(); 0062 * connect(job, &KAuth::ExecuteJob::result, this, &MyApp::actionResult); 0063 * job->start(); 0064 * } 0065 * 0066 * void MyApp::actionResult(KJob *kjob) 0067 * { 0068 * auto job = qobject_cast<KAuth::ExecuteJob *>(kjob); 0069 * qDebug() << job.error() << job.data(); 0070 * } 0071 * @endcode 0072 * 0073 * @since 4.4 0074 */ 0075 class KAUTHCORE_EXPORT Action 0076 { 0077 Q_GADGET 0078 public: 0079 /** 0080 * The three values set by authorization methods 0081 */ 0082 enum AuthStatus { 0083 DeniedStatus, ///< The authorization has been denied by the authorization backend 0084 ErrorStatus, ///< An error occurred 0085 InvalidStatus, ///< An invalid action cannot be authorized 0086 AuthorizedStatus, ///< The authorization has been granted by the authorization backend 0087 AuthRequiredStatus, ///< The user could obtain the authorization after authentication 0088 UserCancelledStatus, ///< The user pressed Cancel the authentication dialog. Currently used only on the mac 0089 }; 0090 Q_ENUM(AuthStatus) 0091 0092 enum ExecutionMode { 0093 ExecuteMode, 0094 AuthorizeOnlyMode, 0095 }; 0096 Q_ENUM(ExecutionMode) 0097 0098 /** 0099 * The backend specific details. 0100 */ 0101 enum class AuthDetail { 0102 DetailOther = 0, 0103 DetailMessage, ///< The message to show in authentication dialog. 0104 }; 0105 Q_ENUM(AuthDetail) 0106 0107 /** 0108 * Map of details. 0109 */ 0110 typedef QMap<AuthDetail, QVariant> DetailsMap; 0111 0112 /** 0113 * @brief Default constructor 0114 * 0115 * This constructor sets the name to the empty string. 0116 * Such an action is invalid and cannot be authorized nor executed, so 0117 * you need to call setName() before you can use the object. 0118 */ 0119 Action(); 0120 0121 /** Copy constructor */ 0122 Action(const Action &action); 0123 0124 /** 0125 * This creates a new action object with this name 0126 * @param name The name of the new action 0127 */ 0128 Action(const QString &name); 0129 0130 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71) 0131 /** 0132 * This creates a new action object with this name and details 0133 * @param name The name of the new action 0134 * @param details The details of the action 0135 * 0136 * @see setDetails 0137 * @deprecated since 5.68, use constructor with DetailsMap 0138 */ 0139 KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use constructor with DetailsMap") 0140 Action(const QString &name, const QString &details); 0141 #endif 0142 0143 /** 0144 * This creates a new action object with this name and details 0145 * @param name The name of the new action 0146 * @param details The details of the action 0147 * 0148 * @see setDetails 0149 * @since 5.68 0150 */ 0151 Action(const QString &name, const DetailsMap &details); 0152 0153 /// Virtual destructor 0154 ~Action(); 0155 0156 /// Assignment operator 0157 Action &operator=(const Action &action); 0158 0159 /** 0160 * @brief Comparison operator 0161 * 0162 * This comparison operator compares the <b>names</b> of two 0163 * actions and returns whether they are the same. It does not 0164 * care about the arguments stored in the actions. However, 0165 * if two actions are invalid they'll match as equal, even 0166 * if the invalid names are different. 0167 * 0168 * @returns true if the two actions are the same or both invalid 0169 */ 0170 bool operator==(const Action &action) const; 0171 0172 /** 0173 * @brief Negated comparison operator 0174 * 0175 * Returns the negation of operator== 0176 * 0177 * @returns true if the two actions are different and not both invalid 0178 */ 0179 bool operator!=(const Action &action) const; 0180 0181 /** 0182 * @brief Gets the action's name. 0183 * 0184 * This is the unique attribute that identifies 0185 * an action object. Two action objects with the same 0186 * name always refer to the same action. 0187 * 0188 * @return The action name 0189 */ 0190 QString name() const; 0191 0192 /** 0193 * @brief Sets the action's name. 0194 * 0195 * It's not common to change the action name 0196 * after its creation. Usually you set the name 0197 * with the constructor (and you have to, because 0198 * there's no default constructor) 0199 */ 0200 void setName(const QString &name); 0201 0202 /** 0203 * @brief Gets the action's timeout. 0204 * 0205 * The timeout of the action in milliseconds 0206 * -1 means the default D-Bus timeout (usually 25 seconds) 0207 * 0208 * @since 5.29 0209 * 0210 * @return The action timeouts 0211 */ 0212 int timeout() const; 0213 0214 /** 0215 * @brief Sets the action's timeout. 0216 * 0217 * The timeout of the action in milliseconds 0218 * -1 means the default D-Bus timeout (usually 25 seconds) 0219 * 0220 * @since 5.29 0221 * 0222 */ 0223 void setTimeout(int timeout); 0224 0225 #if __has_include(<chrono>) 0226 /** 0227 * Convenience overload suporting C++ chrono types. May also be used with chrono literals. 0228 * @since 5.93 0229 */ 0230 void setTimeout(std::chrono::milliseconds msec) 0231 { 0232 setTimeout(int(msec.count())); 0233 } 0234 #endif 0235 0236 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71) 0237 /** 0238 * @brief Sets the action's details 0239 * 0240 * You can use this function to provide the user more details 0241 * (if the backend supports it) on the action being authorized in 0242 * the authorization dialog 0243 * 0244 * @deprecated since 5.68, use setDetailsV2() with DetailsMap. 0245 */ 0246 KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use setDetailsV2() with DetailsMap") 0247 void setDetails(const QString &details); 0248 #endif 0249 0250 /** 0251 * @brief Sets the action's details 0252 * 0253 * You can use this function to provide the user more details 0254 * (if the backend supports it) on the action being authorized in 0255 * the authorization dialog 0256 * 0257 * @param details the details describing the action. For e.g, "DetailMessage" key can 0258 * be used to give a customized authentication message. 0259 * 0260 * @since 5.68 0261 */ 0262 void setDetailsV2(const DetailsMap &details); 0263 0264 #if KAUTHCORE_ENABLE_DEPRECATED_SINCE(5, 71) 0265 /** 0266 * @brief Gets the action's details 0267 * 0268 * The details that will be shown in the authorization dialog, if the 0269 * backend supports it. 0270 * 0271 * @return The action's details 0272 * @deprecated since 5.68, use detailsV2() with DetailsMap. 0273 */ 0274 KAUTHCORE_DEPRECATED_VERSION_BELATED(5, 71, 5, 68, "Use detailsV2() with DetailsMap") 0275 QString details() const; 0276 #endif 0277 0278 /** 0279 * @brief Gets the action's details 0280 * 0281 * The details that will be shown in the authorization dialog, if the 0282 * backend supports it. 0283 * 0284 * @return The action's details 0285 * @since 5.68 0286 */ 0287 DetailsMap detailsV2() const; 0288 0289 /** 0290 * @brief Returns if the object represents a valid action 0291 * 0292 * Action names have to respect a simple syntax. 0293 * They have to be all in lowercase characters, separated 0294 * by dots. Dots can't appear at the beginning and at the end of 0295 * the name. 0296 * 0297 * In other words, the action name has to match this perl-like 0298 * regular expression: 0299 * @code 0300 * /^[a-z]+(\.[a-z]+)*$/ 0301 * @endcode 0302 * 0303 * This method returns @c false if the action name doesn't match the 0304 * valid syntax. 0305 * 0306 * If the backend supports it, this method also checks if the action is 0307 * valid and recognized by the backend itself. 0308 * @note This may spawn a nested event loop. 0309 * 0310 * Invalid actions cannot be authorized nor executed. 0311 * The empty string is not a valid action name, so the default 0312 * constructor returns an invalid action. 0313 */ 0314 bool isValid() const; 0315 0316 /** 0317 * @brief Gets the default helper ID used for actions execution 0318 * 0319 * The helper ID is the string that uniquely identifies the helper in 0320 * the system. It is the string passed to the KAUTH_HELPER_MAIN() macro 0321 * in the helper source. Because one could have different helpers, 0322 * you need to specify an helper ID for each execution, or set a default 0323 * ID by calling setHelperId(). This method returns the current default 0324 * value. 0325 * 0326 * @return The default helper ID. 0327 */ 0328 QString helperId() const; 0329 0330 /** 0331 * @brief Sets the default helper ID used for actions execution 0332 * 0333 * This method sets the helper ID which contains the body of this action. 0334 * If the string is non-empty, the corresponding helper will be fired and 0335 * the action executed inside the helper. Otherwise, the action will be just 0336 * authorized. 0337 * 0338 * @note To unset a previously set helper, just pass an empty string 0339 * 0340 * @param id The default helper ID. 0341 * 0342 * @see hasHelper 0343 * @see helperId 0344 */ 0345 void setHelperId(const QString &id); 0346 0347 /** 0348 * @brief Checks if the action has an helper 0349 * 0350 * This function can be used to check if an helper will be called upon the 0351 * execution of an action. Such an helper can be set through setHelperId(). If 0352 * this function returns false, upon execution the action will be just authorized. 0353 * 0354 * @since 4.5 0355 * 0356 * @return Whether the action has an helper or not 0357 * 0358 * @see setHelperId 0359 */ 0360 bool hasHelper() const; 0361 0362 /** 0363 * @brief Sets the map object used to pass arguments to the helper. 0364 * 0365 * This method sets the variant map that the application 0366 * can use to pass arbitrary data to the helper when executing the action. 0367 * 0368 * Only non-gui variants are supported. 0369 * 0370 * @param arguments The new arguments map 0371 */ 0372 void setArguments(const QVariantMap &arguments); 0373 0374 /** 0375 * @brief Returns map object used to pass arguments to the helper. 0376 * 0377 * This method returns the variant map that the application 0378 * can use to pass arbitrary data to the helper when executing the action. 0379 * 0380 * @return The arguments map that will be passed to the helper. 0381 */ 0382 QVariantMap arguments() const; 0383 0384 /** 0385 * @brief Convenience method to add an argument. 0386 * 0387 * This method adds the pair @c key/value to the QVariantMap used to 0388 * send custom data to the helper. 0389 * 0390 * Use this method if you don't want to create a new QVariantMap only to 0391 * add a new entry. 0392 * 0393 * @param key The new entry's key 0394 * @param value The value of the new entry 0395 */ 0396 void addArgument(const QString &key, const QVariant &value); 0397 0398 /** 0399 * @brief Gets information about the authorization status of an action 0400 * 0401 * This methods query the authorization backend to know if the user can try 0402 * to acquire the authorization for this action. If the result is Action::AuthRequired, 0403 * the user can try to acquire the authorization by authenticating. 0404 * 0405 * It should not be needed to call this method directly, because the execution methods 0406 * already take care of all the authorization stuff. 0407 * 0408 * @return @c Action::Denied if the user doesn't have the authorization to execute the action, 0409 * @c Action::Authorized if the action can be executed, 0410 * @c Action::AuthRequired if the user could acquire the authorization after authentication, 0411 * @c Action::UserCancelled if the user cancels the authentication dialog. Not currently supported by the Polkit backend 0412 */ 0413 AuthStatus status() const; 0414 0415 /** 0416 * @brief Get the job object used to execute the action 0417 * 0418 * @return The KAuth::ExecuteJob object to be used to run the action. 0419 */ 0420 ExecuteJob *execute(ExecutionMode mode = ExecuteMode); 0421 0422 /** 0423 * @brief Sets a parent widget for the authentication dialog 0424 * 0425 * This function is used for explicitly setting a parent window for an eventual authentication dialog required when 0426 * authorization is triggered. Some backends, in fact, (like polkit-1) need to have a parent explicitly set for displaying 0427 * the dialog correctly. 0428 * 0429 * @note If you are using KAuth through one of KDE's GUI components (KPushButton, KCModule...) you do not need and should not 0430 * call this function, as it is already done by the component itself. 0431 * 0432 * @since 4.6 0433 * 0434 * @param parent A QWidget which will be used as the dialog's parent 0435 */ 0436 void setParentWidget(QWidget *parent); 0437 0438 /** 0439 * @brief Returns the parent widget for the authentication dialog for this action 0440 * 0441 * @since 4.6 0442 * 0443 * @returns A QWidget which will is being used as the dialog's parent 0444 */ 0445 QWidget *parentWidget() const; 0446 0447 private: 0448 QSharedDataPointer<ActionData> d; 0449 }; 0450 0451 } // namespace Auth 0452 0453 #endif