diff --git a/core/polkitqt1-authority.h b/core/polkitqt1-authority.h --- a/core/polkitqt1-authority.h +++ b/core/polkitqt1-authority.h @@ -46,6 +46,8 @@ namespace PolkitQt1 { +typedef QMap DetailsMap; + /** * \class Authority polkitqt1-authority.h Authority * \author Daniel Nicoletti @@ -210,6 +212,22 @@ void checkAuthorization(const QString &actionId, const Subject &subject, AuthorizationFlags flags); + /** + * This function does the same as checkAuthorization(const QString&, const + * Subject&, AuthorizationFlags), but also accepts a + * DetailsMap parameter. This map can contain key/value pairs that, for + * example, are used to expand placeholders in polkit authentication + * messages that are formatted like "Authentication required to access + * $(device)". For this example, when a key "device" exists in the map, + * the "$(device)" will be replaced by the corresponding value in the map. + * + * \see checkAuthorization(const QString&, const Subject&, AuthorizationFlags) Base version of this method. + */ + // TODO: merge with checkAuthorization when we decide to break binary compatibility probably in Plasma 6 + void checkAuthorizationWithDetails( + const QString &actionId, const Subject &subject, + AuthorizationFlags flags, const DetailsMap &details); + /** * Synchronous version of the checkAuthorization method. * @@ -222,6 +240,18 @@ Result checkAuthorizationSync(const QString &actionId, const Subject &subject, AuthorizationFlags flags); + /** + * This function does the same as checkAuthorizationSync(const QString&, + * const Subject&, AuthorizationFlags), but also accepts a DetailsMap + * parameter. + * + * \see checkAuthorization(const QString&, const Subject&, AuthorizationFlags, const DetailsMap&) for a description of the details parameter. + * + * \see checkAuthorizationSync(const QString&, const Subject, AuthorizationFlags) Base version of this method. + */ + Result checkAuthorizationSyncWithDetails(const QString &actionId, const Subject &subject, + AuthorizationFlags flags, const DetailsMap &details); + /** * This method can be used to cancel last authorization check. */ diff --git a/core/polkitqt1-authority.cpp b/core/polkitqt1-authority.cpp --- a/core/polkitqt1-authority.cpp +++ b/core/polkitqt1-authority.cpp @@ -123,7 +123,13 @@ *m_revokeTemporaryAuthorizationsCancellable, *m_revokeTemporaryAuthorizationCancellable; - + /** + * \brief Convert a Qt DetailsMap to the lower level PolkitDetails type + * + * The returned pointer needs to be freed via g_object_unref when no + * longer needed. Returns nullptr if details is empty. + */ + static PolkitDetails* convertDetailsMap(const DetailsMap &details); static void pk_config_changed(); static void checkAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data); static void enumerateActionsCallback(GObject *object, GAsyncResult *result, gpointer user_data); @@ -316,6 +322,23 @@ d->m_lastError = E_None; } +PolkitDetails* Authority::Private::convertDetailsMap(const DetailsMap &details) +{ + if (details.empty()) + return nullptr; + + auto ret = polkit_details_new(); + + for (const auto &entry: details.toStdMap()) { + const auto &key = entry.first; + const auto &value = entry.second; + + polkit_details_insert(ret, key.toUtf8().constData(), value.toUtf8().data()); + } + + return ret; +} + void Authority::Private::pk_config_changed() { Q_EMIT Authority::instance()->configChanged(); @@ -326,7 +349,7 @@ return d->pkAuthority; } -Authority::Result Authority::checkAuthorizationSync(const QString &actionId, const Subject &subject, AuthorizationFlags flags) +Authority::Result Authority::checkAuthorizationSyncWithDetails(const QString &actionId, const Subject &subject, AuthorizationFlags flags, const DetailsMap &details) { PolkitAuthorizationResult *pk_result; GError *error = NULL; @@ -340,14 +363,20 @@ return Unknown; } + auto pk_details = Authority::Private::convertDetailsMap(details); + pk_result = polkit_authority_check_authorization_sync(d->pkAuthority, subject.subject(), actionId.toLatin1().data(), - NULL, + pk_details, (PolkitCheckAuthorizationFlags)(int)flags, NULL, &error); + if (pk_details) { + g_object_unref(pk_details); + } + if (error != NULL) { d->setError(E_CheckFailed, error->message); g_error_free(error); @@ -364,7 +393,12 @@ } } -void Authority::checkAuthorization(const QString &actionId, const Subject &subject, AuthorizationFlags flags) +Authority::Result Authority::checkAuthorizationSync(const QString &actionId, const Subject &subject, AuthorizationFlags flags) +{ + return checkAuthorizationSyncWithDetails(actionId, subject, flags, DetailsMap()); +} + +void Authority::checkAuthorizationWithDetails(const QString &actionId, const Subject &subject, AuthorizationFlags flags, const DetailsMap &details) { if (Authority::instance()->hasError()) { return; @@ -375,13 +409,24 @@ return; } + auto pk_details = Authority::Private::convertDetailsMap(details); + polkit_authority_check_authorization(d->pkAuthority, subject.subject(), actionId.toLatin1().data(), - NULL, + pk_details, (PolkitCheckAuthorizationFlags)(int)flags, d->m_checkAuthorizationCancellable, d->checkAuthorizationCallback, this); + + if (pk_details) { + g_object_unref(pk_details); + } +} + +void Authority::checkAuthorization(const QString &actionId, const Subject &subject, AuthorizationFlags flags) +{ + checkAuthorizationWithDetails(actionId, subject, flags, DetailsMap()); } void Authority::Private::checkAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data)