KAuth

kauthexecutejob.cpp
1 /*
2  SPDX-FileCopyrightText: 2009-2012 Dario Freddi <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "kauthexecutejob.h"
8 #include "BackendsManager.h"
9 
10 #include "BackendsManager.h"
11 #include "kauthdebug.h"
12 
13 #include <QEventLoop>
14 #include <QHash>
15 #include <QTimer>
16 
17 namespace KAuth
18 {
19 class Q_DECL_HIDDEN ExecuteJob::Private
20 {
21 public:
22  Private(ExecuteJob *parent)
23  : q(parent)
24  {
25  }
26 
27  ExecuteJob *q;
28  Action action;
29 
30  Action::ExecutionMode mode;
31  QVariantMap data;
32 
33  void doExecuteAction();
34  void doAuthorizeAction();
35  void actionPerformedSlot(const QString &action, const ActionReply &reply);
36  void progressStepSlot(const QString &action, int i);
37  void progressStepSlot(const QString &action, const QVariantMap &data);
38  void statusChangedSlot(const QString &action, KAuth::Action::AuthStatus status);
39 };
40 
41 static QHash<QString, ExecuteJob *> s_watchers;
42 
43 ExecuteJob::ExecuteJob(const Action &action, Action::ExecutionMode mode, QObject *parent)
44  : KJob(parent)
45  , d(new Private(this))
46 {
47  d->action = action;
48  d->mode = mode;
49 
50  HelperProxy *helper = BackendsManager::helperProxy();
51 
52  connect(helper, &KAuth::HelperProxy::actionPerformed, this, [this](const QString &action, const ActionReply &reply) {
53  d->actionPerformedSlot(action, reply);
54  });
55  connect(helper, &KAuth::HelperProxy::progressStep, this, [this](const QString &action, int i) {
56  d->progressStepSlot(action, i);
57  });
58  connect(helper, &KAuth::HelperProxy::progressStepData, this, [this](const QString &action, const QVariantMap &data) {
59  d->progressStepSlot(action, data);
60  });
61 
62  connect(BackendsManager::authBackend(), &KAuth::AuthBackend::actionStatusChanged, this, [this](const QString &action, Action::AuthStatus status) {
63  d->statusChangedSlot(action, status);
64  });
65 }
66 
68 {
69  delete d;
70 }
71 
73 {
74  return d->action;
75 }
76 
77 QVariantMap ExecuteJob::data() const
78 {
79  return d->data;
80 }
81 
83 {
84  if (!d->action.isValid()) {
85  qCWarning(KAUTH) << "Tried to start an invalid action: " << d->action.name();
87  reply.setErrorDescription(tr("Tried to start an invalid action"));
88  d->actionPerformedSlot(d->action.name(), reply);
89  return;
90  }
91 
92  switch (d->mode) {
93  case Action::ExecuteMode:
94  QTimer::singleShot(0, this, [this]() {
95  d->doExecuteAction();
96  });
97  break;
98  case Action::AuthorizeOnlyMode:
99  QTimer::singleShot(0, this, [this]() {
100  d->doAuthorizeAction();
101  });
102  break;
103  default: {
105  reply.setErrorDescription(tr("Unknown execution mode chosen"));
106  d->actionPerformedSlot(d->action.name(), reply);
107  break;
108  }
109  }
110 }
111 
112 bool ExecuteJob::kill(KillVerbosity verbosity)
113 {
114  BackendsManager::helperProxy()->stopAction(d->action.name(), d->action.helperId());
115  KJob::kill(verbosity);
116  return true;
117 }
118 
119 void ExecuteJob::Private::doExecuteAction()
120 {
121  // If this action authorizes from the client, let's do it now
122  if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) {
123  if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) {
124  BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget());
125  }
126 
127  Action::AuthStatus s = BackendsManager::authBackend()->authorizeAction(action.name());
128 
129  if (s == Action::AuthorizedStatus) {
130  if (action.hasHelper()) {
131  BackendsManager::helperProxy()->executeAction(action.name(), action.helperId(), action.detailsV2(), action.arguments(), action.timeout());
132  } else {
133  // Done
134  actionPerformedSlot(action.name(), ActionReply::SuccessReply());
135  }
136  } else {
137  // Abort if authorization fails
138  switch (s) {
140  actionPerformedSlot(action.name(), ActionReply::AuthorizationDeniedReply());
141  break;
143  actionPerformedSlot(action.name(), ActionReply::InvalidActionReply());
144  break;
146  actionPerformedSlot(action.name(), ActionReply::UserCancelledReply());
147  break;
148  default: {
150  r.setErrorDescription(tr("Unknown status for the authentication procedure"));
151  actionPerformedSlot(action.name(), r);
152  break;
153  }
154  }
155  }
156  } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) {
157  if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) {
158  BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget());
159  }
160  if (!action.hasHelper()) {
162  r.setErrorDescription(tr("The current backend only allows helper authorization, but this action does not have a helper."));
163  actionPerformedSlot(action.name(), r);
164  return;
165  }
166  BackendsManager::helperProxy()->executeAction(action.name(), action.helperId(), action.detailsV2(), action.arguments(), action.timeout());
167  } else {
168  // There's something totally wrong here
170  r.setErrorDescription(tr("The backend does not specify how to authorize"));
171  actionPerformedSlot(action.name(), r);
172  }
173 }
174 
175 void ExecuteJob::Private::doAuthorizeAction()
176 {
177  // Check the status first
178  Action::AuthStatus s = action.status();
179  if (s == Action::AuthRequiredStatus) {
180  // Let's check what to do
181  if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) {
182  // In this case we can actually try an authorization
183  if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) {
184  BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget());
185  }
186 
187  s = BackendsManager::authBackend()->authorizeAction(action.name());
188  } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) {
189  // In this case, just throw out success, as the auth will take place later
191  } else {
192  // This should never, never happen
194  r.setErrorDescription(tr("The backend does not specify how to authorize"));
195  actionPerformedSlot(action.name(), r);
196  }
197  }
198 
199  // Return based on the current status
200  if (s == Action::AuthorizedStatus) {
201  actionPerformedSlot(action.name(), ActionReply::SuccessReply());
202  } else {
203  actionPerformedSlot(action.name(), ActionReply::AuthorizationDeniedReply());
204  }
205 }
206 
207 void ExecuteJob::Private::actionPerformedSlot(const QString &taction, const ActionReply &reply)
208 {
209  if (taction == action.name()) {
210  if (reply.failed()) {
211  q->setError(reply.errorCode());
212  q->setErrorText(reply.errorDescription());
213  } else {
214  data = reply.data();
215  }
216 
217  q->emitResult();
218  }
219 }
220 
221 void ExecuteJob::Private::progressStepSlot(const QString &taction, int i)
222 {
223  if (taction == action.name()) {
224  q->setPercent(i);
225  }
226 }
227 
228 void ExecuteJob::Private::progressStepSlot(const QString &taction, const QVariantMap &data)
229 {
230  if (taction == action.name()) {
231  Q_EMIT q->newData(data);
232  }
233 }
234 
235 void ExecuteJob::Private::statusChangedSlot(const QString &taction, Action::AuthStatus status)
236 {
237  if (taction == action.name()) {
238  Q_EMIT q->statusChanged(status);
239  }
240 }
241 
242 } // namespace Auth
243 
244 #include "moc_kauthexecutejob.cpp"
The user pressed Cancel the authentication dialog. Currently used only on the mac.
Definition: kauthaction.h:83
bool kill(KillVerbosity verbosity=Quietly)
The user could obtain the authorization after authentication.
Definition: kauthaction.h:82
~ExecuteJob() override
Virtual destructor.
QVariantMap data() const
Use this to get the data set in the action by HelperSupport::progressStep(QVariant) or returned at th...
static const ActionReply InvalidActionReply()
errorCode() == InvalidAction
An invalid action cannot be authorized.
Definition: kauthaction.h:80
Action action() const
The authorization has been granted by the authorization backend.
Definition: kauthaction.h:81
bool kill(KillVerbosity verbosity=Quietly)
Attempts to halt the execution of the action associated with this job.
The underlying backend reported an error.
QVariantMap data() const
Returns the custom data coming from the helper.
void setErrorDescription(const QString &error)
Sets a human-readble description of the error.
static const ActionReply SuccessReply()
An empty successful reply. Same as using the default constructor.
The authorization has been denied by the authorization backend.
Definition: kauthaction.h:78
AuthStatus
The three values set by authorization methods.
Definition: kauthaction.h:77
bool failed() const
Returns true if type() != Success.
static const ActionReply AuthorizationDeniedReply()
errorCode() == AuthorizationDenied
ActionReply()
Default constructor. Sets type() to Success and errorCode() to zero.
static const ActionReply UserCancelledReply()
errorCode() == UserCancelled
Class that encapsulates a reply coming from the helper after executing an action. ...
Error errorCode() const
Returns the error code of an error reply.
QString errorDescription() const
Gets a human-readble description of the error, if available.
Class to access, authorize and execute actions.
Definition: kauthaction.h:70
void start() override
Starts the job asynchronously.
You tried to execute an invalid action object.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Dec 2 2021 22:48:01 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.