malcontent-control: Add polkit policy support
Add an unlock screen to the application, which is shown on startup if the current user doesn’t have permission to view the parental controls of other users. It requests permission using a new polkit action which implies the various accounts-service actions we need. This adds a dependency on `polkit-gobject-1`. Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
parent
36162c2c23
commit
8badee7fa9
5 changed files with 179 additions and 5 deletions
|
@ -27,6 +27,7 @@
|
|||
#include <glib/gi18n-lib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <polkit/polkit.h>
|
||||
|
||||
#include "application.h"
|
||||
#include "user-controls.h"
|
||||
|
@ -39,6 +40,12 @@ static void user_selector_notify_user_cb (GObject *obj,
|
|||
static void user_manager_notify_is_loaded_cb (GObject *obj,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data);
|
||||
static void permission_new_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
static void permission_notify_allowed_cb (GObject *obj,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -53,13 +60,19 @@ struct _MctApplication
|
|||
{
|
||||
GtkApplication parent_instance;
|
||||
|
||||
GCancellable *cancellable; /* (owned) */
|
||||
|
||||
ActUserManager *user_manager; /* (owned) */
|
||||
|
||||
GPermission *permission; /* (owned) */
|
||||
GError *permission_error; /* (nullable) (owned) */
|
||||
|
||||
MctUserSelector *user_selector;
|
||||
MctUserControls *user_controls;
|
||||
GtkStack *main_stack;
|
||||
GtkLabel *error_title;
|
||||
GtkLabel *error_message;
|
||||
GtkLockButton *lock_button;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MctApplication, mct_application, GTK_TYPE_APPLICATION)
|
||||
|
@ -67,7 +80,7 @@ G_DEFINE_TYPE (MctApplication, mct_application, GTK_TYPE_APPLICATION)
|
|||
static void
|
||||
mct_application_init (MctApplication *self)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
self->cancellable = g_cancellable_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -93,6 +106,8 @@ mct_application_dispose (GObject *object)
|
|||
{
|
||||
MctApplication *self = MCT_APPLICATION (object);
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
|
||||
if (self->user_manager != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->user_manager,
|
||||
|
@ -100,6 +115,16 @@ mct_application_dispose (GObject *object)
|
|||
g_clear_object (&self->user_manager);
|
||||
}
|
||||
|
||||
if (self->permission != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (self->permission,
|
||||
permission_notify_allowed_cb, self);
|
||||
g_clear_object (&self->permission);
|
||||
}
|
||||
|
||||
g_clear_error (&self->permission_error);
|
||||
g_clear_object (&self->cancellable);
|
||||
|
||||
G_OBJECT_CLASS (mct_application_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -126,6 +151,11 @@ mct_application_activate (GApplication *application)
|
|||
g_type_ensure (MCT_TYPE_USER_CONTROLS);
|
||||
g_type_ensure (MCT_TYPE_USER_SELECTOR);
|
||||
|
||||
/* Start loading the permission */
|
||||
polkit_permission_new ("org.freedesktop.MalcontentControl.administration",
|
||||
NULL, self->cancellable,
|
||||
permission_new_cb, self);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
|
||||
g_assert (self->user_manager == NULL);
|
||||
|
@ -146,6 +176,7 @@ mct_application_activate (GApplication *application)
|
|||
self->user_controls = MCT_USER_CONTROLS (gtk_builder_get_object (builder, "user_controls"));
|
||||
self->error_title = GTK_LABEL (gtk_builder_get_object (builder, "error_title"));
|
||||
self->error_message = GTK_LABEL (gtk_builder_get_object (builder, "error_message"));
|
||||
self->lock_button = GTK_LOCK_BUTTON (gtk_builder_get_object (builder, "lock_button"));
|
||||
|
||||
/* Connect signals. */
|
||||
g_signal_connect_object (self->user_selector, "notify::user",
|
||||
|
@ -181,16 +212,19 @@ mct_application_class_init (MctApplicationClass *klass)
|
|||
static void
|
||||
update_main_stack (MctApplication *self)
|
||||
{
|
||||
gboolean is_user_manager_loaded;
|
||||
gboolean is_user_manager_loaded, is_permission_loaded, has_permission;
|
||||
const gchar *new_page_name, *old_page_name;
|
||||
GtkWidget *new_focus_widget;
|
||||
|
||||
/* The implementation of #ActUserManager guarantees that once is-loaded is
|
||||
* true, it is never reset to false. */
|
||||
g_object_get (self->user_manager, "is-loaded", &is_user_manager_loaded, NULL);
|
||||
is_permission_loaded = (self->permission != NULL || self->permission_error != NULL);
|
||||
has_permission = (self->permission != NULL && g_permission_get_allowed (self->permission));
|
||||
|
||||
/* Handle any loading errors. */
|
||||
if (is_user_manager_loaded && act_user_manager_no_service (self->user_manager))
|
||||
/* Handle any loading errors (including those from getting the permission). */
|
||||
if ((is_user_manager_loaded && act_user_manager_no_service (self->user_manager)) ||
|
||||
self->permission_error != NULL)
|
||||
{
|
||||
gtk_label_set_label (self->error_title,
|
||||
_("Failed to load user data from the system"));
|
||||
|
@ -200,7 +234,15 @@ update_main_stack (MctApplication *self)
|
|||
new_page_name = "error";
|
||||
new_focus_widget = NULL;
|
||||
}
|
||||
else if (is_user_manager_loaded)
|
||||
else if (is_permission_loaded && !has_permission)
|
||||
{
|
||||
gtk_lock_button_set_permission (self->lock_button, self->permission);
|
||||
mct_user_controls_set_permission (self->user_controls, self->permission);
|
||||
|
||||
new_page_name = "unlock";
|
||||
new_focus_widget = GTK_WIDGET (self->lock_button);
|
||||
}
|
||||
else if (is_permission_loaded && is_user_manager_loaded)
|
||||
{
|
||||
new_page_name = "controls";
|
||||
new_focus_widget = GTK_WIDGET (self->user_selector);
|
||||
|
@ -242,6 +284,45 @@ user_manager_notify_is_loaded_cb (GObject *obj,
|
|||
update_main_stack (self);
|
||||
}
|
||||
|
||||
static void
|
||||
permission_new_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
MctApplication *self = MCT_APPLICATION (user_data);
|
||||
g_autoptr(GPermission) permission = NULL;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
|
||||
permission = polkit_permission_new_finish (result, &local_error);
|
||||
if (permission == NULL)
|
||||
{
|
||||
g_assert (self->permission_error == NULL);
|
||||
self->permission_error = g_steal_pointer (&local_error);
|
||||
g_debug ("Error getting permission: %s", self->permission_error->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (self->permission == NULL);
|
||||
self->permission = g_steal_pointer (&permission);
|
||||
|
||||
g_signal_connect (self->permission, "notify::allowed",
|
||||
G_CALLBACK (permission_notify_allowed_cb), self);
|
||||
}
|
||||
|
||||
/* Recalculate the UI. */
|
||||
update_main_stack (self);
|
||||
}
|
||||
|
||||
static void
|
||||
permission_notify_allowed_cb (GObject *obj,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MctApplication *self = MCT_APPLICATION (user_data);
|
||||
|
||||
update_main_stack (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* mct_application_new:
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue