[evolution-ews/wip/mcrha/office365: 18/50] Add impersonate settings




commit 0abdbc44b76bc3d1b65423e26c98c8b788824ca2
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jun 17 10:43:40 2020 +0200

    Add impersonate settings

 src/Office365/common/camel-o365-settings.c         | 123 ++++++++++++++
 src/Office365/common/camel-o365-settings.h         |  12 ++
 src/Office365/common/e-o365-connection.c           | 187 ++++++++++++++++++---
 .../evolution/e-mail-config-o365-backend.c         |  35 ++++
 4 files changed, 332 insertions(+), 25 deletions(-)
---
diff --git a/src/Office365/common/camel-o365-settings.c b/src/Office365/common/camel-o365-settings.c
index c103962f..52579232 100644
--- a/src/Office365/common/camel-o365-settings.c
+++ b/src/Office365/common/camel-o365-settings.c
@@ -24,12 +24,14 @@
 
 struct _CamelO365SettingsPrivate {
        GMutex property_lock;
+       gboolean use_impersonation;
        gboolean check_all;
        gboolean filter_junk;
        gboolean filter_junk_inbox;
        gboolean override_oauth2;
        guint timeout;
        guint concurrent_connections;
+       gchar *impersonate_user;
        gchar *email;
        gchar *oauth2_tenant;
        gchar *oauth2_client_id;
@@ -48,6 +50,8 @@ enum {
        PROP_SECURITY_METHOD,
        PROP_TIMEOUT,
        PROP_USER,
+       PROP_USE_IMPERSONATION,
+       PROP_IMPERSONATE_USER,
        PROP_OVERRIDE_OAUTH2,
        PROP_OAUTH2_TENANT,
        PROP_OAUTH2_CLIENT_ID,
@@ -126,6 +130,18 @@ o365_settings_set_property (GObject *object,
                                g_value_get_string (value));
                        return;
 
+               case PROP_USE_IMPERSONATION:
+                       camel_o365_settings_set_use_impersonation (
+                               CAMEL_O365_SETTINGS (object),
+                               g_value_get_boolean (value));
+                       return;
+
+               case PROP_IMPERSONATE_USER:
+                       camel_o365_settings_set_impersonate_user (
+                               CAMEL_O365_SETTINGS (object),
+                               g_value_get_string (value));
+                       return;
+
                case PROP_OVERRIDE_OAUTH2:
                        camel_o365_settings_set_override_oauth2 (
                                CAMEL_O365_SETTINGS (object),
@@ -237,6 +253,20 @@ o365_settings_get_property (GObject *object,
                                CAMEL_NETWORK_SETTINGS (object)));
                        return;
 
+               case PROP_USE_IMPERSONATION:
+                       g_value_set_boolean (
+                               value,
+                               camel_o365_settings_get_use_impersonation (
+                               CAMEL_O365_SETTINGS (object)));
+                       return;
+
+               case PROP_IMPERSONATE_USER:
+                       g_value_take_string (
+                               value,
+                               camel_o365_settings_dup_impersonate_user (
+                               CAMEL_O365_SETTINGS (object)));
+                       return;
+
                case PROP_OVERRIDE_OAUTH2:
                        g_value_set_boolean (
                                value,
@@ -392,6 +422,30 @@ camel_o365_settings_class_init (CamelO365SettingsClass *class)
                PROP_USER,
                "user");
 
+       g_object_class_install_property (
+               object_class,
+               PROP_USE_IMPERSONATION,
+               g_param_spec_boolean (
+                       "use-impersonation",
+                       "Use Impersonation",
+                       "Use Impersonation",
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_IMPERSONATE_USER,
+               g_param_spec_string (
+                       "impersonate-user",
+                       "Impersonate User",
+                       "Impersonate User",
+                       NULL,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
+
        g_object_class_install_property (
                object_class,
                PROP_OVERRIDE_OAUTH2,
@@ -500,6 +554,75 @@ camel_o365_settings_get_from_backend (struct _EBackend *backend,
        return CAMEL_O365_SETTINGS (settings);
 }
 
+gboolean
+camel_o365_settings_get_use_impersonation (CamelO365Settings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_O365_SETTINGS (settings), FALSE);
+
+       return settings->priv->use_impersonation;
+}
+
+void
+camel_o365_settings_set_use_impersonation (CamelO365Settings *settings,
+                                          gboolean use_impersonation)
+{
+       g_return_if_fail (CAMEL_IS_O365_SETTINGS (settings));
+
+       if ((settings->priv->use_impersonation ? 1 : 0) == (use_impersonation ? 1 : 0))
+               return;
+
+       settings->priv->use_impersonation = use_impersonation;
+
+       g_object_notify (G_OBJECT (settings), "use-impersonation");
+}
+
+const gchar *
+camel_o365_settings_get_impersonate_user (CamelO365Settings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_O365_SETTINGS (settings), NULL);
+
+       return settings->priv->impersonate_user;
+}
+
+gchar *
+camel_o365_settings_dup_impersonate_user (CamelO365Settings *settings)
+{
+       const gchar *protected;
+       gchar *duplicate;
+
+       g_return_val_if_fail (CAMEL_IS_O365_SETTINGS (settings), NULL);
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       protected = camel_o365_settings_get_impersonate_user (settings);
+       duplicate = g_strdup (protected);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       return duplicate;
+}
+
+void
+camel_o365_settings_set_impersonate_user (CamelO365Settings *settings,
+                                         const gchar *impersonate_user)
+{
+       g_return_if_fail (CAMEL_IS_O365_SETTINGS (settings));
+
+       g_mutex_lock (&settings->priv->property_lock);
+
+       if (g_strcmp0 (settings->priv->impersonate_user, impersonate_user) == 0) {
+               g_mutex_unlock (&settings->priv->property_lock);
+               return;
+       }
+
+       g_free (settings->priv->impersonate_user);
+       settings->priv->impersonate_user = e_util_strdup_strip (impersonate_user);
+
+       g_mutex_unlock (&settings->priv->property_lock);
+
+       g_object_notify (G_OBJECT (settings), "impersonate-user");
+}
+
 gboolean
 camel_o365_settings_get_check_all (CamelO365Settings *settings)
 {
diff --git a/src/Office365/common/camel-o365-settings.h b/src/Office365/common/camel-o365-settings.h
index 3f05b178..8cc038be 100644
--- a/src/Office365/common/camel-o365-settings.h
+++ b/src/Office365/common/camel-o365-settings.h
@@ -66,6 +66,18 @@ CamelO365Settings *
                camel_o365_settings_get_from_backend
                                                (struct _EBackend *backend,
                                                 struct _ESourceRegistry *registry);
+gboolean       camel_o365_settings_get_use_impersonation
+                                               (CamelO365Settings *settings);
+void           camel_o365_settings_set_use_impersonation
+                                               (CamelO365Settings *settings,
+                                                gboolean use_impersonation);
+const gchar *  camel_o365_settings_get_impersonate_user
+                                               (CamelO365Settings *settings);
+gchar *                camel_o365_settings_dup_impersonate_user
+                                               (CamelO365Settings *settings);
+void           camel_o365_settings_set_impersonate_user
+                                               (CamelO365Settings *settings,
+                                                const gchar *impersonate_user);
 gboolean       camel_o365_settings_get_check_all
                                                (CamelO365Settings *settings);
 void           camel_o365_settings_set_check_all
diff --git a/src/Office365/common/e-o365-connection.c b/src/Office365/common/e-o365-connection.c
index ca1fc975..1f6db867 100644
--- a/src/Office365/common/e-o365-connection.c
+++ b/src/Office365/common/e-o365-connection.c
@@ -45,6 +45,9 @@ struct _EO365ConnectionPrivate {
        GProxyResolver *proxy_resolver;
        ESoupAuthBearer *bearer_auth;
 
+       gchar *user; /* The default user for the URL */
+       gchar *impersonate_user;
+
        gboolean ssl_info_set;
        gchar *ssl_certificate_pem;
        GTlsCertificateFlags ssl_certificate_errors;
@@ -62,7 +65,10 @@ enum {
        PROP_PROXY_RESOLVER,
        PROP_SETTINGS,
        PROP_SOURCE,
-       PROP_CONCURRENT_CONNECTIONS
+       PROP_CONCURRENT_CONNECTIONS,
+       PROP_USER,                      /* This one is hidden, write only */
+       PROP_USE_IMPERSONATION,         /* This one is hidden, write only */
+       PROP_IMPERSONATE_USER           /* This one is hidden, write only */
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (EO365Connection, e_o365_connection, G_TYPE_OBJECT)
@@ -326,6 +332,24 @@ o365_connection_set_settings (EO365Connection *cnc,
        g_return_if_fail (cnc->priv->settings == NULL);
 
        cnc->priv->settings = g_object_ref (settings);
+
+       e_binding_bind_property (
+               cnc->priv->settings, "user",
+               cnc, "user",
+               G_BINDING_DEFAULT |
+               G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               cnc->priv->settings, "use-impersonation",
+               cnc, "use-impersonation",
+               G_BINDING_DEFAULT |
+               G_BINDING_SYNC_CREATE);
+
+       /* No need to G_BINDING_SYNC_CREATE, because the 'use-impersonation' already updated the value */
+       e_binding_bind_property (
+               cnc->priv->settings, "impersonate-user",
+               cnc, "impersonate-user",
+               G_BINDING_DEFAULT);
 }
 
 static void
@@ -339,6 +363,62 @@ o365_connection_set_source (EO365Connection *cnc,
        cnc->priv->source = g_object_ref (source);
 }
 
+static void
+o365_connection_take_user (EO365Connection *cnc,
+                          gchar *user)
+{
+       g_return_if_fail (E_IS_O365_CONNECTION (cnc));
+
+       LOCK (cnc);
+
+       if (!user || !*user)
+               g_clear_pointer (&user, g_free);
+
+       g_free (cnc->priv->user);
+       cnc->priv->user = user;
+
+       UNLOCK (cnc);
+}
+
+static void
+o365_connection_take_impersonate_user (EO365Connection *cnc,
+                                      gchar *impersonate_user)
+{
+       g_return_if_fail (E_IS_O365_CONNECTION (cnc));
+
+       LOCK (cnc);
+
+       if (!impersonate_user || !*impersonate_user ||
+           !camel_o365_settings_get_use_impersonation (cnc->priv->settings)) {
+               g_clear_pointer (&impersonate_user, g_free);
+       }
+
+       if (g_strcmp0 (impersonate_user, cnc->priv->impersonate_user) != 0) {
+               g_free (cnc->priv->impersonate_user);
+               cnc->priv->impersonate_user = impersonate_user;
+       } else {
+               g_clear_pointer (&impersonate_user, g_free);
+       }
+
+       UNLOCK (cnc);
+}
+
+static void
+o365_connection_set_use_impersonation (EO365Connection *cnc,
+                                      gboolean use_impersonation)
+{
+       g_return_if_fail (E_IS_O365_CONNECTION (cnc));
+
+       LOCK (cnc);
+
+       if (!use_impersonation)
+               o365_connection_take_impersonate_user (cnc, NULL);
+       else
+               o365_connection_take_impersonate_user (cnc, camel_o365_settings_dup_impersonate_user 
(cnc->priv->settings));
+
+       UNLOCK (cnc);
+}
+
 static void
 o365_connection_set_property (GObject *object,
                              guint property_id,
@@ -369,6 +449,24 @@ o365_connection_set_property (GObject *object,
                                E_O365_CONNECTION (object),
                                g_value_get_uint (value));
                        return;
+
+               case PROP_USER:
+                       o365_connection_take_user (
+                               E_O365_CONNECTION (object),
+                               g_value_dup_string (value));
+                       return;
+
+               case PROP_USE_IMPERSONATION:
+                       o365_connection_set_use_impersonation (
+                               E_O365_CONNECTION (object),
+                               g_value_get_boolean (value));
+                       return;
+
+               case PROP_IMPERSONATE_USER:
+                       o365_connection_take_impersonate_user (
+                               E_O365_CONNECTION (object),
+                               g_value_dup_string (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -494,6 +592,8 @@ o365_connection_finalize (GObject *object)
 
        g_rec_mutex_clear (&cnc->priv->property_lock);
        g_clear_pointer (&cnc->priv->ssl_certificate_pem, g_free);
+       g_clear_pointer (&cnc->priv->user, g_free);
+       g_clear_pointer (&cnc->priv->impersonate_user, g_free);
        g_free (cnc->priv->hash_key);
 
        /* Chain up to parent's method. */
@@ -561,6 +661,39 @@ e_o365_connection_class_init (EO365ConnectionClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_EXPLICIT_NOTIFY |
                        G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_USER,
+               g_param_spec_string (
+                       "user",
+                       NULL,
+                       NULL,
+                       NULL,
+                       G_PARAM_WRITABLE |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_USE_IMPERSONATION,
+               g_param_spec_boolean (
+                       "use-impersonation",
+                       NULL,
+                       NULL,
+                       FALSE,
+                       G_PARAM_WRITABLE |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_IMPERSONATE_USER,
+               g_param_spec_string (
+                       "impersonate-user",
+                       NULL,
+                       NULL,
+                       NULL,
+                       G_PARAM_WRITABLE |
+                       G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -1195,35 +1328,29 @@ e_o365_construct_uri (EO365Connection *cnc,
        }
 
        if (include_user) {
-               if (user_override) {
+               const gchar *use_user;
+
+               LOCK (cnc);
+
+               if (user_override)
+                       use_user = user_override;
+               else if (cnc->priv->impersonate_user)
+                       use_user = cnc->priv->impersonate_user;
+               else
+                       use_user = cnc->priv->user;
+
+               if (use_user) {
                        gchar *encoded;
 
-                       encoded = soup_uri_encode (user_override, NULL);
+                       encoded = soup_uri_encode (use_user, NULL);
 
                        g_string_append_c (uri, '/');
                        g_string_append (uri, encoded);
 
                        g_free (encoded);
-               } else {
-                       CamelO365Settings *settings;
-                       gchar *user;
-
-                       settings = e_o365_connection_get_settings (cnc);
-                       user = camel_network_settings_dup_user (CAMEL_NETWORK_SETTINGS (settings));
-
-                       if (user && *user) {
-                               gchar *encoded;
-
-                               encoded = soup_uri_encode (user, NULL);
-
-                               g_string_append_c (uri, '/');
-                               g_string_append (uri, encoded);
-
-                               g_free (encoded);
-                       }
-
-                       g_free (user);
                }
+
+               UNLOCK (cnc);
        }
 
        if (resource && *resource) {
@@ -1419,10 +1546,20 @@ e_o365_connection_authenticate_sync (EO365Connection *cnc,
 
                        bearer = e_o365_connection_ref_bearer_auth (cnc);
 
-                       if (bearer)
-                               result = E_SOURCE_AUTHENTICATION_REJECTED;
-                       else
+                       if (bearer) {
+                               LOCK (cnc);
+
+                               if (cnc->priv->impersonate_user) {
+                                       g_propagate_error (error, local_error);
+                                       local_error = NULL;
+                               } else {
+                                       result = E_SOURCE_AUTHENTICATION_REJECTED;
+                               }
+
+                               UNLOCK (cnc);
+                       } else {
                                result = E_SOURCE_AUTHENTICATION_REQUIRED;
+                       }
 
                        g_clear_object (&bearer);
                        g_clear_error (&local_error);
diff --git a/src/Office365/evolution/e-mail-config-o365-backend.c 
b/src/Office365/evolution/e-mail-config-o365-backend.c
index eedad28a..73781265 100644
--- a/src/Office365/evolution/e-mail-config-o365-backend.c
+++ b/src/Office365/evolution/e-mail-config-o365-backend.c
@@ -33,6 +33,7 @@
 
 struct _EMailConfigO365BackendPrivate {
        GtkWidget *user_entry;
+       GtkWidget *impersonate_user_entry;
        GtkGrid *oauth2_settings_grid;
        GtkWidget *oauth2_override_check;
        GtkWidget *oauth2_tenant_entry;
@@ -204,6 +205,40 @@ mail_config_o365_backend_insert_widgets (EMailConfigServiceBackend *backend,
        o365_backend->priv->user_entry = widget;  /* do not reference */
        gtk_widget_show (widget);
 
+       widget = gtk_check_button_new_with_mnemonic (_("Open _Mailbox of other user"));
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+       gtk_widget_show (widget);
+
+       if (camel_o365_settings_get_use_impersonation (CAMEL_O365_SETTINGS (settings))) {
+               const gchar *impersonate_user = camel_o365_settings_get_impersonate_user (CAMEL_O365_SETTINGS 
(settings));
+
+               if (impersonate_user && !*impersonate_user) {
+                       camel_o365_settings_set_impersonate_user (CAMEL_O365_SETTINGS (settings), NULL);
+                       camel_o365_settings_set_use_impersonation (CAMEL_O365_SETTINGS (settings), FALSE);
+               }
+       }
+
+       e_binding_bind_property (
+               settings, "use-impersonation",
+               widget, "active",
+               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
+       gtk_widget_show (widget);
+       o365_backend->priv->impersonate_user_entry = widget;  /* do not reference */
+
+       e_binding_bind_object_text_property (
+               settings, "impersonate-user",
+               widget, "text",
+               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+       e_binding_bind_property (
+               settings, "use-impersonation",
+               widget, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
        text = _("Authentication");
        markup = g_markup_printf_escaped ("<b>%s</b>", text);
        widget = gtk_label_new (markup);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]