Warning, file /frameworks/kauth/src/executejob.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2009-2012 Dario Freddi <drf@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "executejob.h" 0008 0009 #include "BackendsManager.h" 0010 #include "kauthdebug.h" 0011 0012 #include <QCoreApplication> 0013 #include <QEventLoop> 0014 #include <QHash> 0015 #include <QTimer> 0016 0017 namespace KAuth 0018 { 0019 class ExecuteJobPrivate 0020 { 0021 Q_DECLARE_TR_FUNCTIONS(KAuth::ExecuteJob) 0022 0023 public: 0024 explicit ExecuteJobPrivate(ExecuteJob *parent) 0025 : q(parent) 0026 { 0027 } 0028 0029 ExecuteJob *q; 0030 Action action; 0031 0032 Action::ExecutionMode mode; 0033 QVariantMap data; 0034 0035 void doExecuteAction(); 0036 void doAuthorizeAction(); 0037 void actionPerformedSlot(const QString &action, const ActionReply &reply); 0038 void progressStepSlot(const QString &action, int i); 0039 void progressStepSlot(const QString &action, const QVariantMap &data); 0040 void statusChangedSlot(const QString &action, KAuth::Action::AuthStatus status); 0041 }; 0042 0043 static QHash<QString, ExecuteJob *> s_watchers; 0044 0045 ExecuteJob::ExecuteJob(const Action &action, Action::ExecutionMode mode, QObject *parent) 0046 : KJob(parent) 0047 , d(new ExecuteJobPrivate(this)) 0048 { 0049 d->action = action; 0050 d->mode = mode; 0051 0052 HelperProxy *helper = BackendsManager::helperProxy(); 0053 0054 connect(helper, &KAuth::HelperProxy::actionPerformed, this, [this](const QString &action, const ActionReply &reply) { 0055 d->actionPerformedSlot(action, reply); 0056 }); 0057 connect(helper, &KAuth::HelperProxy::progressStep, this, [this](const QString &action, int i) { 0058 d->progressStepSlot(action, i); 0059 }); 0060 connect(helper, &KAuth::HelperProxy::progressStepData, this, [this](const QString &action, const QVariantMap &data) { 0061 d->progressStepSlot(action, data); 0062 }); 0063 0064 connect(BackendsManager::authBackend(), &KAuth::AuthBackend::actionStatusChanged, this, [this](const QString &action, Action::AuthStatus status) { 0065 d->statusChangedSlot(action, status); 0066 }); 0067 } 0068 0069 ExecuteJob::~ExecuteJob() = default; 0070 0071 Action ExecuteJob::action() const 0072 { 0073 return d->action; 0074 } 0075 0076 QVariantMap ExecuteJob::data() const 0077 { 0078 return d->data; 0079 } 0080 0081 void ExecuteJob::start() 0082 { 0083 if (!d->action.isValid()) { 0084 qCWarning(KAUTH) << "Tried to start an invalid action: " << d->action.name(); 0085 ActionReply reply(ActionReply::InvalidActionError); 0086 reply.setErrorDescription(tr("Tried to start an invalid action")); 0087 d->actionPerformedSlot(d->action.name(), reply); 0088 return; 0089 } 0090 0091 switch (d->mode) { 0092 case Action::ExecuteMode: 0093 QTimer::singleShot(0, this, [this]() { 0094 d->doExecuteAction(); 0095 }); 0096 break; 0097 case Action::AuthorizeOnlyMode: 0098 QTimer::singleShot(0, this, [this]() { 0099 d->doAuthorizeAction(); 0100 }); 0101 break; 0102 default: { 0103 ActionReply reply(ActionReply::InvalidActionError); 0104 reply.setErrorDescription(tr("Unknown execution mode chosen")); 0105 d->actionPerformedSlot(d->action.name(), reply); 0106 break; 0107 } 0108 } 0109 } 0110 0111 bool ExecuteJob::kill(KillVerbosity verbosity) 0112 { 0113 BackendsManager::helperProxy()->stopAction(d->action.name(), d->action.helperId()); 0114 KJob::kill(verbosity); 0115 return true; 0116 } 0117 0118 void ExecuteJobPrivate::doExecuteAction() 0119 { 0120 // If this action authorizes from the client, let's do it now 0121 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 0122 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 0123 BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget()); 0124 } 0125 0126 Action::AuthStatus s = BackendsManager::authBackend()->authorizeAction(action.name()); 0127 0128 if (s == Action::AuthorizedStatus) { 0129 if (action.hasHelper()) { 0130 BackendsManager::helperProxy()->executeAction(action.name(), action.helperId(), action.detailsV2(), action.arguments(), action.timeout()); 0131 } else { 0132 // Done 0133 actionPerformedSlot(action.name(), ActionReply::SuccessReply()); 0134 } 0135 } else { 0136 // Abort if authorization fails 0137 switch (s) { 0138 case Action::DeniedStatus: 0139 actionPerformedSlot(action.name(), ActionReply::AuthorizationDeniedReply()); 0140 break; 0141 case Action::InvalidStatus: 0142 actionPerformedSlot(action.name(), ActionReply::InvalidActionReply()); 0143 break; 0144 case Action::UserCancelledStatus: 0145 actionPerformedSlot(action.name(), ActionReply::UserCancelledReply()); 0146 break; 0147 default: { 0148 ActionReply r(ActionReply::BackendError); 0149 r.setErrorDescription(tr("Unknown status for the authentication procedure")); 0150 actionPerformedSlot(action.name(), r); 0151 break; 0152 } 0153 } 0154 } 0155 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 0156 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 0157 BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget()); 0158 } 0159 if (!action.hasHelper()) { 0160 ActionReply r(ActionReply::InvalidActionReply()); 0161 r.setErrorDescription(tr("The current backend only allows helper authorization, but this action does not have a helper.")); 0162 actionPerformedSlot(action.name(), r); 0163 return; 0164 } 0165 BackendsManager::helperProxy()->executeAction(action.name(), action.helperId(), action.detailsV2(), action.arguments(), action.timeout()); 0166 } else { 0167 // There's something totally wrong here 0168 ActionReply r(ActionReply::BackendError); 0169 r.setErrorDescription(tr("The backend does not specify how to authorize")); 0170 actionPerformedSlot(action.name(), r); 0171 } 0172 } 0173 0174 void ExecuteJobPrivate::doAuthorizeAction() 0175 { 0176 // Check the status first 0177 Action::AuthStatus s = action.status(); 0178 if (s == Action::AuthRequiredStatus) { 0179 // Let's check what to do 0180 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 0181 // In this case we can actually try an authorization 0182 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 0183 BackendsManager::authBackend()->preAuthAction(action.name(), action.parentWidget()); 0184 } 0185 0186 s = BackendsManager::authBackend()->authorizeAction(action.name()); 0187 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 0188 // In this case, just throw out success, as the auth will take place later 0189 s = Action::AuthorizedStatus; 0190 } else { 0191 // This should never, never happen 0192 ActionReply r(ActionReply::BackendError); 0193 r.setErrorDescription(tr("The backend does not specify how to authorize")); 0194 actionPerformedSlot(action.name(), r); 0195 } 0196 } 0197 0198 // Return based on the current status 0199 if (s == Action::AuthorizedStatus) { 0200 actionPerformedSlot(action.name(), ActionReply::SuccessReply()); 0201 } else { 0202 actionPerformedSlot(action.name(), ActionReply::AuthorizationDeniedReply()); 0203 } 0204 } 0205 0206 void ExecuteJobPrivate::actionPerformedSlot(const QString &taction, const ActionReply &reply) 0207 { 0208 if (taction == action.name()) { 0209 if (reply.failed()) { 0210 q->setError(reply.errorCode()); 0211 q->setErrorText(reply.errorDescription()); 0212 } else { 0213 data = reply.data(); 0214 } 0215 0216 q->emitResult(); 0217 } 0218 } 0219 0220 void ExecuteJobPrivate::progressStepSlot(const QString &taction, int i) 0221 { 0222 if (taction == action.name()) { 0223 q->setPercent(i); 0224 } 0225 } 0226 0227 void ExecuteJobPrivate::progressStepSlot(const QString &taction, const QVariantMap &data) 0228 { 0229 if (taction == action.name()) { 0230 Q_EMIT q->newData(data); 0231 } 0232 } 0233 0234 void ExecuteJobPrivate::statusChangedSlot(const QString &taction, Action::AuthStatus status) 0235 { 0236 if (taction == action.name()) { 0237 Q_EMIT q->statusChanged(status); 0238 } 0239 } 0240 0241 } // namespace Auth 0242 0243 #include "moc_executejob.cpp"