mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-26 14:13:26 +00:00
system-helper: Add RemoveLocalRef helper function
This depends on the modify-repo privilege Closes: #1034 Approved by: alexlarsson
This commit is contained in:
parent
6236a60a1b
commit
3f91b4d883
@ -6974,10 +6974,36 @@ flatpak_dir_remove_ref (FlatpakDir *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
if (!ostree_repo_set_ref_immediate (self->repo, remote_name, ref, NULL, cancellable, error))
|
||||
if (flatpak_dir_use_system_helper (self, NULL))
|
||||
{
|
||||
const char *installation = flatpak_dir_get_id (self);
|
||||
FlatpakSystemHelper *system_helper = flatpak_dir_get_system_helper (self);
|
||||
|
||||
/* If we don't have the system helper, we'll have to try and just remove
|
||||
* the ref as an unprivileged user, which might fail later */
|
||||
if (system_helper)
|
||||
{
|
||||
if (!flatpak_system_helper_call_remove_local_ref_sync (system_helper,
|
||||
remote_name,
|
||||
ref,
|
||||
installation ? installation : "",
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ostree_repo_set_ref_immediate (self->repo,
|
||||
remote_name,
|
||||
ref,
|
||||
NULL,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return flatpak_dir_prune (self, cancellable, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -7033,58 +7059,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
filter_out_deployed_refs (FlatpakDir *self,
|
||||
GHashTable *local_refs)
|
||||
{
|
||||
GHashTable *undeployed_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_autoptr(GVariant) deploy_data = NULL;
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key;
|
||||
|
||||
g_hash_table_iter_init (&hash_iter, local_refs);
|
||||
while (g_hash_table_iter_next (&hash_iter, &key, NULL))
|
||||
{
|
||||
g_autoptr(GVariant) deploy_data = flatpak_dir_get_deploy_data (self, key, NULL, NULL);
|
||||
|
||||
if (!deploy_data)
|
||||
g_hash_table_add (undeployed_refs, g_strdup (key));
|
||||
}
|
||||
|
||||
return undeployed_refs;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_dir_cleanup_undeployed_refs (FlatpakDir *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GHashTable) local_refs = NULL;
|
||||
g_autoptr(GHashTable) undeployed_refs = NULL;
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key;
|
||||
|
||||
if (!ostree_repo_list_refs (self->repo, NULL, &local_refs, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
undeployed_refs = filter_out_deployed_refs (self, local_refs);
|
||||
g_hash_table_iter_init (&hash_iter, undeployed_refs);
|
||||
|
||||
while (g_hash_table_iter_next (&hash_iter, &key, NULL))
|
||||
{
|
||||
g_autofree gchar *remote = NULL;
|
||||
g_autofree gchar *ref = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (key, &remote, &ref, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_remove_ref (self, remote, ref, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_dir_prune (FlatpakDir *self,
|
||||
GCancellable *cancellable,
|
||||
@ -8055,6 +8029,101 @@ flatpak_dir_find_installed_ref (FlatpakDir *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Given a list of refs in local_refspecs, remove any refs that have already
|
||||
* been deployed and return a new GPtrArray containing only the undeployed
|
||||
* refs. This is used by flatpak_dir_cleanup_undeployed_refs to determine
|
||||
* which undeployed refs need to be removed from the local repository.
|
||||
*
|
||||
* Returns: (transfer-full): A #GPtrArray
|
||||
*/
|
||||
static GPtrArray *
|
||||
filter_out_deployed_refs (FlatpakDir *self,
|
||||
GPtrArray *local_refspecs,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) undeployed_refs = g_ptr_array_new_full (local_refspecs->len, g_free);
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < local_refspecs->len; ++i)
|
||||
{
|
||||
const gchar *refspec = g_ptr_array_index (local_refspecs, i);
|
||||
g_autofree gchar *ref = NULL;
|
||||
g_autoptr(GVariant) deploy_data = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (refspec, NULL, &ref, error))
|
||||
return FALSE;
|
||||
|
||||
deploy_data = flatpak_dir_get_deploy_data (self, ref, NULL, NULL);
|
||||
|
||||
if (!deploy_data)
|
||||
g_ptr_array_add (undeployed_refs, g_strdup (refspec));
|
||||
}
|
||||
|
||||
return g_steal_pointer (&undeployed_refs);
|
||||
}
|
||||
|
||||
/**
|
||||
* flatpak_dir_cleanup_undeployed_refs:
|
||||
*
|
||||
* Find all flatpak refs in the local repository which have not been deloyed
|
||||
* in the dir and remove them from the repository. You might want to call this
|
||||
* function if you pulled refs into the dir but then decided that you did
|
||||
* not want to deploy them for some reason. Note that this does not prune
|
||||
* objects bound to the cleaned up refs from the underlying OSTree repository,
|
||||
* you should consider using flatpak_dir_prune to do that.
|
||||
*
|
||||
* @self: a #FlatpakDir
|
||||
* @cancellable: (allow-none): a #GCancellable
|
||||
* @error: (allow-none): a #GError
|
||||
*
|
||||
* Since: 0.10.0
|
||||
* Returns: (transfer-full): %TRUE if cleaning up the refs suceeded, %FALSE
|
||||
* otherwise
|
||||
*/
|
||||
gboolean
|
||||
flatpak_dir_cleanup_undeployed_refs (FlatpakDir *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GHashTable) local_refspecs = NULL;
|
||||
g_autoptr(GPtrArray) local_flatpak_refspecs = NULL;
|
||||
g_autoptr(GPtrArray) undeployed_refs = NULL;
|
||||
gsize i = 0;
|
||||
|
||||
if (!ostree_repo_list_refs (self->repo, NULL, &local_refspecs, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
local_flatpak_refspecs = find_matching_refs (local_refspecs,
|
||||
NULL, NULL, NULL,
|
||||
FLATPAK_KINDS_APP |
|
||||
FLATPAK_KINDS_RUNTIME,
|
||||
FIND_MATCHING_REFS_FLAGS_KEEP_REMOTE,
|
||||
error);
|
||||
|
||||
if (!local_flatpak_refspecs)
|
||||
return FALSE;
|
||||
|
||||
undeployed_refs = filter_out_deployed_refs (self, local_flatpak_refspecs, error);
|
||||
|
||||
if (!undeployed_refs)
|
||||
return FALSE;
|
||||
|
||||
for (; i < undeployed_refs->len; ++i)
|
||||
{
|
||||
const char *refspec = g_ptr_array_index (undeployed_refs, i);
|
||||
g_autofree gchar *remote = NULL;
|
||||
g_autofree gchar *ref = NULL;
|
||||
|
||||
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_dir_remove_ref (self, remote, ref, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static FlatpakDir *
|
||||
flatpak_dir_new_full (GFile *path, gboolean user, DirExtraData *extra_data)
|
||||
{
|
||||
|
||||
@ -111,6 +111,12 @@
|
||||
<arg type='ay' name='summary_sig_path' direction='in'/>
|
||||
</method>
|
||||
|
||||
<method name="RemoveLocalRef">
|
||||
<arg type='s' name='remote' direction='in'/>
|
||||
<arg type='s' name='ref' direction='in'/>
|
||||
<arg type='s' name='installation' direction='in'/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
|
||||
</node>
|
||||
|
||||
@ -790,6 +790,49 @@ handle_update_remote (FlatpakSystemHelper *object,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_remove_local_ref (FlatpakSystemHelper *object,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_remote,
|
||||
const gchar *arg_ref,
|
||||
const gchar *arg_installation)
|
||||
{
|
||||
g_autoptr(FlatpakDir) system = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_debug ("RemoveLocalRef %s %s %s", arg_remote, arg_ref, arg_installation);
|
||||
|
||||
system = dir_get_system (arg_installation, &error);
|
||||
if (system == NULL)
|
||||
{
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (*arg_remote == 0 || strchr (arg_remote, '/') != NULL)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid remote name: %s", arg_remote);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!flatpak_dir_ensure_repo (system, NULL, &error))
|
||||
{
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!flatpak_dir_remove_ref (system, arg_remote, arg_ref, NULL, &error))
|
||||
{
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
flatpak_system_helper_complete_remove_local_ref (object, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
@ -901,6 +944,16 @@ flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
|
||||
|
||||
action = "org.freedesktop.Flatpak.update-remote";
|
||||
|
||||
polkit_details_insert (details, "remote", remote);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "RemoveLocalRef") == 0)
|
||||
{
|
||||
const char *remote;
|
||||
|
||||
g_variant_get_child (parameters, 0, "&s", &remote);
|
||||
|
||||
action = "org.freedesktop.Flatpak.modify-repo";
|
||||
|
||||
polkit_details_insert (details, "remote", remote);
|
||||
}
|
||||
|
||||
@ -958,6 +1011,7 @@ on_bus_acquired (GDBusConnection *connection,
|
||||
g_signal_connect (helper, "handle-install-bundle", G_CALLBACK (handle_install_bundle), NULL);
|
||||
g_signal_connect (helper, "handle-configure-remote", G_CALLBACK (handle_configure_remote), NULL);
|
||||
g_signal_connect (helper, "handle-update-remote", G_CALLBACK (handle_update_remote), NULL);
|
||||
g_signal_connect (helper, "handle-remove-local-ref", G_CALLBACK (handle_remove_local_ref), NULL);
|
||||
|
||||
g_signal_connect (helper, "g-authorize-method",
|
||||
G_CALLBACK (flatpak_authorize_method_handler),
|
||||
|
||||
@ -98,6 +98,21 @@
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.Flatpak.modify-repo">
|
||||
<!-- SECURITY:
|
||||
- Normal users do not need authentication to modify the
|
||||
OSTree repository
|
||||
-->
|
||||
<description>Update system repository</description>
|
||||
<message>Authentication is required to update the system repository</message>
|
||||
<icon_name>package-x-generic</icon_name>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>yes</allow_active>
|
||||
</defaults>
|
||||
</action>
|
||||
|
||||
<action id="org.freedesktop.Flatpak.install-bundle">
|
||||
<description>Install bundle</description>
|
||||
<message>Authentication is required to install software</message>
|
||||
|
||||
@ -2,7 +2,8 @@ polkit.addRule(function(action, subject) {
|
||||
if ((action.id == "org.freedesktop.Flatpak.app-install" ||
|
||||
action.id == "org.freedesktop.Flatpak.runtime-install"||
|
||||
action.id == "org.freedesktop.Flatpak.app-uninstall" ||
|
||||
action.id == "org.freedesktop.Flatpak.runtime-uninstall") &&
|
||||
action.id == "org.freedesktop.Flatpak.runtime-uninstall" ||
|
||||
action.id == "org.freedesktop.Flatpak.modify-repo") &&
|
||||
subject.active == true && subject.local == true &&
|
||||
subject.isInGroup("@privileged_group@")) {
|
||||
return polkit.Result.YES;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user