[shotwell/wip/phako/libsecret: 252/254] wip: Store online service secrets with libsecret



commit 95b264a3c5cd6d168e896d9b4d120113669fa7d7
Author: Jens Georg <mail jensge org>
Date:   Sat Jun 9 02:13:15 2018 +0200

    wip: Store online service secrets with libsecret

 meson.build                                        |  1 +
 .../shotwell/GoogleAuthenticator.vala              | 34 +++++++++++--
 plugins/authenticator/shotwell/meson.build         |  2 +-
 plugins/shotwell-publishing/PiwigoPublishing.vala  | 56 +++++++++++++++++-----
 plugins/shotwell-publishing/meson.build            |  2 +-
 5 files changed, 77 insertions(+), 18 deletions(-)
---
diff --git a/meson.build b/meson.build
index fda28500..7b04d33a 100644
--- a/meson.build
+++ b/meson.build
@@ -64,6 +64,7 @@ gexiv2 = dependency('gexiv2', version: '>= 0.11.0')
 libraw = dependency('libraw', version : '>= 0.13.2')
 libexif = dependency('libexif', version : '>= 0.6.16')
 unity = dependency('unity', required : false)
+secret = dependency('libsecret-1', required: true)
 champlain = dependency('champlain-0.12', version: '>= 0.12.16')
 champlain_gtk = dependency('champlain-gtk-0.12')
 clutter = dependency('clutter-1.0')
diff --git a/plugins/authenticator/shotwell/GoogleAuthenticator.vala 
b/plugins/authenticator/shotwell/GoogleAuthenticator.vala
index 5b38ee66..815df2fa 100644
--- a/plugins/authenticator/shotwell/GoogleAuthenticator.vala
+++ b/plugins/authenticator/shotwell/GoogleAuthenticator.vala
@@ -112,12 +112,15 @@ namespace Publishing.Authenticator.Shotwell.Google {
     }
 
     internal class Google : Spit.Publishing.Authenticator, Object {
+        private const string PASSWORD_SCHEME = "org.gnome.Shotwell.Google";
+
         private string scope = null;
         private Spit.Publishing.PluginHost host = null;
         private GLib.HashTable<string, Variant> params = null;
         private WebAuthenticationPane web_auth_pane = null;
         private Session session = null;
         private string welcome_message = null;
+        private Secret.Schema? schema = null;
 
         public Google(string scope,
                       string welcome_message,
@@ -127,10 +130,17 @@ namespace Publishing.Authenticator.Shotwell.Google {
             this.scope = scope;
             this.session = new Session();
             this.welcome_message = welcome_message;
+            this.schema = new Secret.Schema (PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+                                             "scope", Secret.SchemaAttributeType.STRING);
         }
 
         public void authenticate() {
-            var refresh_token = host.get_config_string("refresh_token", null);
+            string? refresh_token = null;
+            try {
+                refresh_token = Secret.password_lookup_sync(this.schema, null, "scope", this.scope);
+            } catch (Error err) {
+                critical("Failed to lookup refresh_token from password store: %s", err.message);
+            }
             if (refresh_token != null && refresh_token != "") {
                 on_refresh_token_available(refresh_token);
                 do_exchange_refresh_token_for_access_token();
@@ -157,7 +167,11 @@ namespace Publishing.Authenticator.Shotwell.Google {
 
         public void logout() {
             session.deauthenticate();
-            host.set_config_string("refresh_token", "");
+            try {
+                Secret.password_clear_sync(this.schema, null, "scope", this.scope);
+            } catch (Error err) {
+                critical("Failed to remove password for scope %s: %s", this.scope, err.message);
+            }
         }
 
         public void refresh() {
@@ -368,12 +382,17 @@ namespace Publishing.Authenticator.Shotwell.Google {
             // by the time we get a username, the session should be authenticated, or else something
             // really tragic has happened
             assert(session.is_authenticated());
-            host.set_config_string("refresh_token", session.refresh_token);
+            try {
+                Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+                    "Shotwell publishing (Google account scope %s)".printf(this.scope),
+                    session.refresh_token, null, "scope", this.scope);
+            } catch (Error err) {
+                critical("Failed to look up password for scope %s: %s", this.scope, err.message);
+            }
 
             this.authenticated();
         }
 
-
         private void do_exchange_refresh_token_for_access_token() {
             debug("ACTION: exchanging OAuth refresh token for OAuth access token.");
 
@@ -416,7 +435,12 @@ namespace Publishing.Authenticator.Shotwell.Google {
             if (txn.get_status_code() == Soup.Status.BAD_REQUEST ||
                 txn.get_status_code() == Soup.Status.UNAUTHORIZED) {
                 // Refresh token invalid, starting over
-                host.set_config_string("refresh_token", "");
+                try {
+                    Secret.password_clear_sync(this.schema, null, "scope", this.scope);
+                } catch (Error err) {
+                    critical("Failed to remove password for scope %s: %s", this.scope, err.message);
+                }
+
                 Idle.add (() => { this.authenticate(); return false; });
             }
 
diff --git a/plugins/authenticator/shotwell/meson.build b/plugins/authenticator/shotwell/meson.build
index b1a6fd2b..b43b889e 100644
--- a/plugins/authenticator/shotwell/meson.build
+++ b/plugins/authenticator/shotwell/meson.build
@@ -11,7 +11,7 @@ authenticator_shotwell_resources = gnome.compile_resources('authenticator-resour
         source_dir : meson.source_root())
 
 authenticator_shotwell_deps = [gee, gtk, gio, soup, json_glib, sw_plugin,
-                               sw_plugin_common_dep, json_glib, xml, webkit]
+                               sw_plugin_common_dep, json_glib, xml, webkit, secret]
 
 authenticator = library('shotwell-authenticator',
                         authenticator_shotwell_sources + authenticator_shotwell_resources,
diff --git a/plugins/shotwell-publishing/PiwigoPublishing.vala 
b/plugins/shotwell-publishing/PiwigoPublishing.vala
index 8a10eee0..3c232a27 100644
--- a/plugins/shotwell-publishing/PiwigoPublishing.vala
+++ b/plugins/shotwell-publishing/PiwigoPublishing.vala
@@ -123,6 +123,8 @@ internal class PublishingParameters {
 }
 
 public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
+    private const string PASSWORD_SCHEME = "org.gnome.Shotwell.Piwigo";
+
     private Spit.Publishing.Service service;
     private Spit.Publishing.PluginHost host;
     private bool running = false;
@@ -131,6 +133,7 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
     private Category[] categories = null;
     private PublishingParameters parameters = null;
     private Spit.Publishing.ProgressCallback progress_reporter = null;
+    private Secret.Schema? schema = null;
 
     public PiwigoPublisher(Spit.Publishing.Service service,
         Spit.Publishing.PluginHost host) {
@@ -138,6 +141,9 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
         this.service = service;
         this.host = host;
         session = new Session();
+        this.schema = new Secret.Schema (PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+                                         "url", Secret.SchemaAttributeType.STRING,
+                                         "user", Secret.SchemaAttributeType.STRING);
     }
 
     // Publisher interface implementation
@@ -169,7 +175,9 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
             debug("PiwigoPublisher: session is not authenticated.");
             string? persistent_url = get_persistent_url();
             string? persistent_username = get_persistent_username();
-            string? persistent_password = get_persistent_password();
+            string? persistent_password = get_persistent_password(persistent_url, persistent_username);
+
+            // This will only be null if either of the other two was null or the password did not exist
             if (persistent_url != null && persistent_username != null && persistent_password != null)
                 do_network_login(persistent_url, persistent_username,
                     persistent_password, get_remember_password());
@@ -200,12 +208,37 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
         host.set_config_string("username", username);
     }
     
-    public string? get_persistent_password() {
-        return host.get_config_string("password", null);
+    public string? get_persistent_password(string? url, string? user) {
+        if (url != null && user != null) {
+            try {
+                var pw = Secret.password_lookup_sync(this.schema, null, "url", url, "user", user);
+
+                return pw;
+            } catch (Error err) {
+                critical("Failed to lookup the password for url %s and user %s: %s", url, user, err.message);
+
+                return null;
+            }
+        }
+
+        return null;
     }
     
-    private void set_persistent_password(string? password) {
-        host.set_config_string("password", password);
+    private void set_persistent_password(string? url, string? user, string? password) {
+        try {
+            if (password == null) {
+                // remove
+                Secret.password_clear_sync(this.schema, null, "url", url, "user", user);
+            } else {
+                Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+                        "Shotwell publishing (Piwigo account %s@%s)".printf(user, url),
+                        password,
+                        null,
+                        "url", url, "user", user);
+            }
+        } catch (Error err) {
+            critical("Failed to store password for %s@%s: %s", user, url, err.message);
+        }
     }
     
     public bool get_remember_password() {
@@ -300,7 +333,7 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
 
             string? persistent_url = get_persistent_url();
             string? persistent_username = get_persistent_username();
-            string? persistent_password = get_persistent_password();
+            string? persistent_password = get_persistent_password(persistent_url, persistent_username);
             if (persistent_url != null && persistent_username != null && persistent_password != null)
                 do_network_login(persistent_url, persistent_username,
                     persistent_password, get_remember_password());
@@ -350,10 +383,11 @@ public class PiwigoPublisher : Spit.Publishing.Publisher, GLib.Object {
         host.install_login_wait_pane();
         
         set_remember_password(remember_password);
-        if (remember_password)
-            set_persistent_password(password);
-        else
-            set_persistent_password(null);
+        if (remember_password) {
+            set_persistent_password(url, username, password);
+        } else {
+            set_persistent_password(url, username, null);
+        }
 
         SessionLoginTransaction login_trans = new SessionLoginTransaction(
             session, normalise_url(url), username, password);
@@ -1137,7 +1171,7 @@ internal class AuthenticationPane : Shotwell.Plugins.Common.BuilderPane {
             username_entry.set_text(persistent_username);
         }
         password_entry = builder.get_object ("password_entry") as Gtk.Entry;
-        string? persistent_password = publisher.get_persistent_password();
+        string? persistent_password = publisher.get_persistent_password(persistent_url, persistent_username);
         if (persistent_password != null) {
             password_entry.set_text(persistent_password);
         }
diff --git a/plugins/shotwell-publishing/meson.build b/plugins/shotwell-publishing/meson.build
index a5f9ed8f..18c101aa 100644
--- a/plugins/shotwell-publishing/meson.build
+++ b/plugins/shotwell-publishing/meson.build
@@ -18,7 +18,7 @@ shared_module('shotwell-publishing',
               shotwell_publishing_sources + shotwell_publishing_resources,
               dependencies : [gtk, soup, gexiv2, gee, sw_plugin, json_glib,
                               webkit, sw_plugin_common_dep, xml, gdata, gcr,
-                              gcr_ui, authenticator_dep],
+                              gcr_ui, authenticator_dep, secret],
               c_args : ['-DPLUGIN_RESOURCE_PATH="/org/gnome/Shotwell/Publishing"',
                         '-DGCR_API_SUBJECT_TO_CHANGE'],
               install: true,


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