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