KDECore
kauthaction.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright (C) 2009 Nicola Gigante <nicola.gigante@gmail.com> 00003 * Copyright (C) 2009-2010 Dario Freddi <drf@kde.org> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 2.1 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program; if not, write to the 00017 * Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . 00019 */ 00020 00021 #include "kauthaction.h" 00022 00023 #include <QRegExp> 00024 #include <QWidget> 00025 00026 #include "BackendsManager.h" 00027 #include "kauthactionwatcher.h" 00028 00029 namespace KAuth 00030 { 00031 00032 class Action::Private 00033 { 00034 public: 00035 Private() : valid(false), async(false), parent(0) {} 00036 00037 QString name; 00038 QString details; 00039 QString helperId; 00040 QVariantMap args; 00041 bool valid; 00042 bool async; 00043 QWidget *parent; 00044 }; 00045 00046 // Constructors 00047 Action::Action() 00048 : d(new Private()) 00049 { 00050 } 00051 00052 Action::Action(const Action &action) 00053 : d(new Private()) 00054 { 00055 *this = action; 00056 } 00057 00058 Action::Action(const QString &name) 00059 : d(new Private()) 00060 { 00061 setName(name); 00062 BackendsManager::authBackend()->setupAction(d->name); 00063 } 00064 00065 Action::Action(const QString &name, const QString &details) 00066 : d(new Private()) 00067 { 00068 setName(name); 00069 setDetails(details); 00070 BackendsManager::authBackend()->setupAction(d->name); 00071 } 00072 00073 Action::~Action() 00074 { 00075 delete d; 00076 } 00077 00078 // Operators 00079 Action &Action::operator=(const Action & action) 00080 { 00081 setName(action.d->name); 00082 d->args = action.d->args; 00083 00084 return *this; 00085 } 00086 00087 bool Action::operator==(const Action &action) const 00088 { 00089 return d->name == action.d->name; 00090 } 00091 00092 bool Action::operator!=(const Action &action) const 00093 { 00094 return d->name != action.d->name; 00095 } 00096 00097 // Accessors 00098 QString Action::name() const 00099 { 00100 return d->name; 00101 } 00102 00103 void Action::setName(const QString &name) 00104 { 00105 d->name = name; 00106 00107 // Does the backend support checking for known actions? 00108 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::CheckActionExistenceCapability) { 00109 // In this case, just ask the backend 00110 d->valid = BackendsManager::authBackend()->actionExists(name); 00111 } else { 00112 // Otherwise, check through a regexp 00113 QRegExp exp(QLatin1String("[0-z]+(\\.[0-z]+)*")); 00114 d->valid = exp.exactMatch(name); 00115 } 00116 } 00117 00118 QString Action::details() const 00119 { 00120 return d->details; 00121 } 00122 00123 void Action::setDetails(const QString &details) 00124 { 00125 d->details = details; 00126 } 00127 00128 bool Action::isValid() const 00129 { 00130 return d->valid; 00131 } 00132 00133 void Action::setArguments(const QVariantMap &arguments) 00134 { 00135 d->args = arguments; 00136 } 00137 00138 void Action::addArgument(const QString &key, const QVariant &value) 00139 { 00140 d->args.insert(key, value); 00141 } 00142 00143 QVariantMap Action::arguments() const 00144 { 00145 return d->args; 00146 } 00147 00148 ActionWatcher *Action::watcher() 00149 { 00150 return ActionWatcher::watcher(d->name); 00151 } 00152 00153 QString Action::helperID() const 00154 { 00155 return d->helperId; 00156 } 00157 00158 // TODO: Check for helper id's syntax 00159 void Action::setHelperID(const QString &id) 00160 { 00161 d->helperId = id; 00162 } 00163 00164 void Action::setParentWidget(QWidget* parent) 00165 { 00166 d->parent = parent; 00167 } 00168 00169 QWidget* Action::parentWidget() const 00170 { 00171 return d->parent; 00172 } 00173 00174 00175 // Authorizaton methods 00176 Action::AuthStatus Action::authorize() const 00177 { 00178 if (!isValid()) { 00179 return Action::Invalid; 00180 } 00181 00182 // If there is any pre auth action, let's perform it 00183 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 00184 BackendsManager::authBackend()->preAuthAction(d->name, d->parent); 00185 } 00186 00187 // Let's check capabilities 00188 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 00189 // That's easy then 00190 return BackendsManager::authBackend()->authorizeAction(d->name); 00191 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 00192 // We need to check if we have an helper in this case 00193 if (hasHelper()) { 00194 // Ok, we need to use "helper authorization". 00195 return BackendsManager::helperProxy()->authorizeAction(d->name, d->helperId); 00196 } else { 00197 // Ok, in this case we have to fake and just pretend we are an helper 00198 if (BackendsManager::authBackend()->isCallerAuthorized(d->name, BackendsManager::authBackend()->callerID())) { 00199 return Authorized; 00200 } else { 00201 return Denied; 00202 } 00203 } 00204 } else { 00205 // This should never, never happen 00206 return Invalid; 00207 } 00208 } 00209 00210 00211 Action::AuthStatus Action::earlyAuthorize() const 00212 { 00213 // Check the status first 00214 AuthStatus s = status(); 00215 if (s == AuthRequired) { 00216 // Let's check what to do 00217 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 00218 // In this case we can actually try an authorization 00219 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 00220 BackendsManager::authBackend()->preAuthAction(d->name, d->parent); 00221 } 00222 00223 return BackendsManager::authBackend()->authorizeAction(d->name); 00224 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 00225 // In this case, just throw out Authorized, as the auth will take place later 00226 return Authorized; 00227 } else { 00228 // This should never, never happen 00229 return Invalid; 00230 } 00231 } else { 00232 // It's fine, return the status 00233 return s; 00234 } 00235 } 00236 00237 00238 Action::AuthStatus Action::status() const 00239 { 00240 if (!isValid()) { 00241 return Action::Invalid; 00242 } 00243 00244 return BackendsManager::authBackend()->actionStatus(d->name); 00245 } 00246 00247 // Execution methods 00248 bool Action::executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId) 00249 { 00250 return executeActions(actions, deniedActions, helperId, 0); 00251 } 00252 00253 bool Action::executeActions(const QList< Action >& actions, QList< Action >* deniedActions, const QString& helperId, QWidget* parent) 00254 { 00255 QList<QPair<QString, QVariantMap> > list; 00256 00257 foreach(const Action &a, actions) { 00258 // Save us an additional step 00259 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 00260 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 00261 BackendsManager::authBackend()->preAuthAction(a.name(), parent); 00262 } 00263 00264 AuthStatus s = BackendsManager::authBackend()->authorizeAction(a.name()); 00265 00266 if (s == Authorized) { 00267 list.push_back(QPair<QString, QVariantMap>(a.name(), a.arguments())); 00268 } else if ((s == Denied || s == Invalid) && deniedActions) { 00269 *deniedActions << a; 00270 } 00271 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 00272 list.push_back(QPair<QString, QVariantMap>(a.name(), a.arguments())); 00273 } else { 00274 // There's something totally wrong here 00275 return false; 00276 } 00277 } 00278 00279 if (list.isEmpty()) { 00280 return false; 00281 } 00282 00283 return BackendsManager::helperProxy()->executeActions(list, helperId); 00284 } 00285 00286 bool Action::executesAsync() const 00287 { 00288 return d->async; 00289 } 00290 00291 void Action::setExecutesAsync(bool async) 00292 { 00293 d->async = async; 00294 } 00295 00296 ActionReply Action::execute() const 00297 { 00298 if (!isValid()) 00299 return ActionReply::InvalidActionReply; 00300 00301 return execute(helperID()); 00302 } 00303 00304 ActionReply Action::execute(const QString &helperID) const 00305 { 00306 // Is the action valid? 00307 if (!isValid()) { 00308 return Invalid; 00309 } 00310 00311 // What to do? 00312 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromClientCapability) { 00313 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 00314 BackendsManager::authBackend()->preAuthAction(d->name, d->parent); 00315 } 00316 // Authorize from here 00317 AuthStatus s = BackendsManager::authBackend()->authorizeAction(d->name); 00318 00319 // Abort if authorization fails 00320 switch (s) { 00321 case Denied: 00322 return ActionReply::AuthorizationDeniedReply; 00323 case Invalid: 00324 return ActionReply::InvalidActionReply; 00325 case UserCancelled: 00326 return ActionReply::UserCancelledReply; 00327 default: 00328 break; 00329 } 00330 } else if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::AuthorizeFromHelperCapability) { 00331 // In this case we care only if the action is not async and does not have an helper 00332 if (!d->async && !hasHelper()) { 00333 // Authorize! 00334 switch (authorize()) { 00335 case Denied: 00336 return ActionReply::AuthorizationDeniedReply; 00337 case Invalid: 00338 return ActionReply::InvalidActionReply; 00339 case UserCancelled: 00340 return ActionReply::UserCancelledReply; 00341 default: 00342 break; 00343 } 00344 } 00345 } else { 00346 // What? 00347 return Invalid; 00348 } 00349 00350 if (d->async) { 00351 if (hasHelper()) { 00352 // It makes no sense 00353 return Invalid; 00354 } 00355 00356 return executeActions(QList<Action>() << *this, NULL, helperID) ? 00357 ActionReply::SuccessReply : ActionReply::AuthorizationDeniedReply; 00358 } else { 00359 if (hasHelper()) { 00360 // Perform the pre auth here 00361 if (BackendsManager::authBackend()->capabilities() & KAuth::AuthBackend::PreAuthActionCapability) { 00362 BackendsManager::authBackend()->preAuthAction(d->name, d->parent); 00363 } 00364 00365 return BackendsManager::helperProxy()->executeAction(d->name, helperID, d->args); 00366 } else { 00367 return ActionReply::SuccessReply; 00368 } 00369 } 00370 } 00371 00372 void Action::stop() 00373 { 00374 stop(helperID()); 00375 } 00376 00377 void Action::stop(const QString &helperID) 00378 { 00379 BackendsManager::helperProxy()->stopAction(d->name, helperID); 00380 } 00381 00382 bool Action::hasHelper() const 00383 { 00384 return !d->helperId.isEmpty(); 00385 } 00386 00387 } // namespace Auth
KDE 4.6 API Reference