[shotwell/wip/phako/libsecret: 15/15] wip: Store online service secrets with libsecret
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [shotwell/wip/phako/libsecret: 15/15] wip: Store online service secrets with libsecret
- Date: Tue, 7 Jan 2020 15:35:36 +0000 (UTC)
commit c6e8b153d69b68ba65ae2db82fa35a1e679cd18f
Author: Jens Georg <mail jensge org>
Date: Sat Jun 9 02:13:15 2018 +0200
wip: Store online service secrets with libsecret
flatpak/org.gnome.Shotwell.json | 3 +-
meson.build | 1 +
.../shotwell/FlickrPublishingAuthenticator.vala | 2 +-
.../shotwell/GoogleAuthenticator.vala | 34 +++++++--
.../shotwell/OAuth1Authenticator.vala | 83 ++++++++++++++++++----
.../shotwell/TumblrAuthenticator.vala | 2 +-
plugins/authenticator/shotwell/meson.build | 2 +-
.../GalleryConnector.vala | 35 ++++++++-
.../RajcePublishing.vala | 40 ++++++++++-
.../YandexPublishing.vala | 28 ++++++--
plugins/shotwell-publishing-extras/meson.build | 2 +-
plugins/shotwell-publishing/PiwigoPublishing.vala | 56 ++++++++++++---
plugins/shotwell-publishing/meson.build | 2 +-
13 files changed, 246 insertions(+), 44 deletions(-)
---
diff --git a/flatpak/org.gnome.Shotwell.json b/flatpak/org.gnome.Shotwell.json
index 29ec23be..b55c4fa0 100644
--- a/flatpak/org.gnome.Shotwell.json
+++ b/flatpak/org.gnome.Shotwell.json
@@ -27,7 +27,8 @@
"--talk-name=org.gnome.SettingsDaemon",
"--talk-name=org.gtk.vfs",
"--talk-name=org.gtk.vfs.*",
- "--env=GSETTINGS_BACKEND=dconf"
+ "--env=GSETTINGS_BACKEND=dconf",
+ "--talk-name=org.freedesktop.secrets"
],
"cleanup" : [
"/include",
diff --git a/meson.build b/meson.build
index 6a06b349..143e9190 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/FlickrPublishingAuthenticator.vala
b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
index 82448e26..49eacf73 100644
--- a/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
+++ b/plugins/authenticator/shotwell/FlickrPublishingAuthenticator.vala
@@ -90,7 +90,7 @@ namespace Publishing.Authenticator.Shotwell.Flickr {
private WebAuthenticationPane pane;
public Flickr(Spit.Publishing.PluginHost host) {
- base(API_KEY, API_SECRET, host);
+ base("Flickr", API_KEY, API_SECRET, host);
}
public override void authenticate() {
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/OAuth1Authenticator.vala
b/plugins/authenticator/shotwell/OAuth1Authenticator.vala
index 39752ece..ca19dc17 100644
--- a/plugins/authenticator/shotwell/OAuth1Authenticator.vala
+++ b/plugins/authenticator/shotwell/OAuth1Authenticator.vala
@@ -11,10 +11,18 @@ namespace Publishing.Authenticator.Shotwell.OAuth1 {
protected GLib.HashTable<string, Variant> params;
protected Publishing.RESTSupport.OAuth1.Session session;
protected Spit.Publishing.PluginHost host;
+ private Secret.Schema? schema = null;
+ private const string SECRET_TYPE_USERNAME = "username";
+ private const string SECRET_TYPE_AUTH_TOKEN = "auth-token";
+ private const string SECRET_TYPE_AUTH_TOKEN_SECRET = "auth-token-secret";
+ private string service = null;
- protected Authenticator(string api_key, string api_secret, Spit.Publishing.PluginHost host) {
+ protected Authenticator(string service, string api_key, string api_secret,
Spit.Publishing.PluginHost host) {
base();
this.host = host;
+ this.service = service;
+ this.schema = new Secret.Schema ("org.gnome.Shotwell." + service, Secret.SchemaFlags.NONE,
+ "type", Secret.SchemaAttributeType.STRING);
params = new GLib.HashTable<string, Variant>(str_hash, str_equal);
params.insert("ConsumerKey", api_key);
@@ -43,9 +51,9 @@ namespace Publishing.Authenticator.Shotwell.OAuth1 {
public abstract void refresh();
public void invalidate_persistent_session() {
- set_persistent_access_phase_token("");
- set_persistent_access_phase_token_secret("");
- set_persistent_access_phase_username("");
+ set_persistent_access_phase_token(null);
+ set_persistent_access_phase_token_secret(null);
+ set_persistent_access_phase_username(null);
}
protected bool is_persistent_session_valid() {
return (get_persistent_access_phase_username() != null &&
@@ -54,27 +62,76 @@ namespace Publishing.Authenticator.Shotwell.OAuth1 {
}
protected string? get_persistent_access_phase_username() {
- return host.get_config_string("access_phase_username", null);
+ try {
+ return Secret.password_lookup_sync(this.schema, null, "type", SECRET_TYPE_USERNAME);
+ } catch (Error err) {
+ critical("Failed to lookup username from password store: %s", err.message);
+ return null;
+ }
}
- protected void set_persistent_access_phase_username(string username) {
- host.set_config_string("access_phase_username", username);
+ protected void set_persistent_access_phase_username(string? username) {
+ try {
+ if (username == null || username == "") {
+ Secret.password_clear_sync(this.schema, null,
+ "type", SECRET_TYPE_USERNAME);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (%s)".printf(this.service),
+ username, null, "type", SECRET_TYPE_USERNAME);
+ }
+ } catch (Error err) {
+ critical("Failed to store username in store: %s", err.message);
+ }
}
protected string? get_persistent_access_phase_token() {
- return host.get_config_string("access_phase_token", null);
+ try {
+ return Secret.password_lookup_sync(this.schema, null,
+ "type", SECRET_TYPE_AUTH_TOKEN);
+ } catch (Error err) {
+ critical("Failed to lookup auth-token from password store: %s", err.message);
+ return null;
+ }
}
- protected void set_persistent_access_phase_token(string token) {
- host.set_config_string("access_phase_token", token);
+ protected void set_persistent_access_phase_token(string? token) {
+ try {
+ if (token == null || token == "") {
+ Secret.password_clear_sync(this.schema, null,
+ "type", SECRET_TYPE_AUTH_TOKEN);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (%s)".printf(this.service),
+ token, null, "type", SECRET_TYPE_AUTH_TOKEN);
+ }
+ } catch (Error err) {
+ critical("Failed to store auth-token store: %s", err.message);
+ }
}
protected string? get_persistent_access_phase_token_secret() {
- return host.get_config_string("access_phase_token_secret", null);
+ try {
+ return Secret.password_lookup_sync(this.schema, null, "type", SECRET_TYPE_AUTH_TOKEN_SECRET);
+ } catch (Error err) {
+ critical("Failed to lookup auth-token-secret from password store: %s", err.message);
+ return null;
+ }
}
- protected void set_persistent_access_phase_token_secret(string secret) {
- host.set_config_string("access_phase_token_secret", secret);
+ protected void set_persistent_access_phase_token_secret(string? secret) {
+ try {
+ if (secret == null || secret == "") {
+ Secret.password_clear_sync(this.schema, null,
+ "type", SECRET_TYPE_AUTH_TOKEN_SECRET);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (%s)".printf(this.service),
+ secret, null, "type", SECRET_TYPE_AUTH_TOKEN_SECRET);
+ }
+ } catch (Error err) {
+ critical("Failed to store auth-token-secret store: %s", err.message);
+ }
}
diff --git a/plugins/authenticator/shotwell/TumblrAuthenticator.vala
b/plugins/authenticator/shotwell/TumblrAuthenticator.vala
index 35fdce98..72904d52 100644
--- a/plugins/authenticator/shotwell/TumblrAuthenticator.vala
+++ b/plugins/authenticator/shotwell/TumblrAuthenticator.vala
@@ -127,7 +127,7 @@ namespace Publishing.Authenticator.Shotwell.Tumblr {
internal class Tumblr : Publishing.Authenticator.Shotwell.OAuth1.Authenticator {
public Tumblr(Spit.Publishing.PluginHost host) {
- base(API_KEY, API_SECRET, host);
+ base("Tumblr", API_KEY, API_SECRET, host);
}
public override void authenticate() {
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-extras/GalleryConnector.vala
b/plugins/shotwell-publishing-extras/GalleryConnector.vala
index 9932862a..2af20871 100644
--- a/plugins/shotwell-publishing-extras/GalleryConnector.vala
+++ b/plugins/shotwell-publishing-extras/GalleryConnector.vala
@@ -65,6 +65,7 @@ public class Gallery3Service : Object, Spit.Pluggable,
if (icon_pixbuf_set == null)
icon_pixbuf_set = Resources.load_from_resource
(Resources.RESOURCE_PATH + "/" + ICON_FILENAME);
+
}
public int get_pluggable_interface(int min_host_interface,
@@ -798,6 +799,7 @@ private class GalleryUploadTransaction :
public class GalleryPublisher : Spit.Publishing.Publisher, GLib.Object {
+ private const string PASSWORD_SCHEME = "org.gnome.Shotwell.Gallery3";
private const string BAD_FILE_MSG = _("\n\nThe file ā%sā may not be supported by or may be too large for
this instance of Gallery3.");
private const string BAD_MOVIE_MSG = _("\nNote that Gallery3 only supports the video types that
Flowplayer does.");
@@ -808,6 +810,7 @@ public class GalleryPublisher : Spit.Publishing.Publisher, GLib.Object {
private bool running = false;
private Album[] albums = null;
private string key = null;
+ private Secret.Schema? schema = null;
private PublishingOptionsPane publishing_options_pane = null;
@@ -816,6 +819,9 @@ public class GalleryPublisher : Spit.Publishing.Publisher, GLib.Object {
this.service = service;
this.host = host;
this.session = new Session();
+ this.schema = new Secret.Schema (PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+ "url", Secret.SchemaAttributeType.STRING,
+ "user", Secret.SchemaAttributeType.STRING);
}
public bool is_running() {
@@ -872,11 +878,34 @@ public class GalleryPublisher : Spit.Publishing.Publisher, GLib.Object {
// Config getters/setters
// API key
internal string? get_api_key() {
- return host.get_config_string("api-key", null);
+ var user = get_gallery_username();
+ var url = get_gallery_url();
+
+ try {
+ return Secret.password_lookup_sync(this.schema, null, "url", url, "user", user);
+ } catch (Error err) {
+ critical ("Failed to get api key for %s@%s: %s", user, url, err.message);
+ }
+
+ return null;
}
- internal void set_api_key(string key) {
- host.set_config_string("api-key", key);
+ internal void set_api_key(string? key) {
+ var user = get_gallery_username();
+ var url = get_gallery_url();
+ try {
+ if (key == null | key == "") {
+ Secret.password_clear_sync(this.schema, null, "url", url, "user", user);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (Gallery3 account %s@%s)".printf(user, url),
+ key,
+ null,
+ "url", url, "user", user);
+ }
+ } catch (Error err) {
+ critical("Failed to store api key for %s@%s: %s", user, url, err.message);
+ }
}
// URL
diff --git a/plugins/shotwell-publishing-extras/RajcePublishing.vala
b/plugins/shotwell-publishing-extras/RajcePublishing.vala
index a0882747..ab27863d 100644
--- a/plugins/shotwell-publishing-extras/RajcePublishing.vala
+++ b/plugins/shotwell-publishing-extras/RajcePublishing.vala
@@ -65,6 +65,7 @@ namespace Publishing.Rajce
public class RajcePublisher : Spit.Publishing.Publisher, GLib.Object
{
+ private const string PASSWORD_SCHEME = "org.gnome.Shotwell.Rajce";
private Spit.Publishing.PluginHost host = null;
private Spit.Publishing.ProgressCallback progress_reporter = null;
private Spit.Publishing.Service service = null;
@@ -80,6 +81,7 @@ public class RajcePublisher : Spit.Publishing.Publisher, GLib.Object
private Album[] albums = null;
private PublishingParameters parameters = null;
private Spit.Publishing.Publisher.MediaType media_type = Spit.Publishing.Publisher.MediaType.NONE;
+ private Secret.Schema schema = null;
public RajcePublisher(Spit.Publishing.Service service, Spit.Publishing.PluginHost host)
{
@@ -90,6 +92,9 @@ public class RajcePublisher : Spit.Publishing.Publisher, GLib.Object
foreach(Spit.Publishing.Publishable p in host.get_publishables())
media_type |= p.get_media_type();
+
+ this.schema = new Secret.Schema(PASSWORD_SCHEME, Secret.SchemaFlags.NONE,
+ "user", Secret.SchemaAttributeType.STRING);
}
private string get_rajce_url()
@@ -140,8 +145,39 @@ public class RajcePublisher : Spit.Publishing.Publisher, GLib.Object
public string? get_url() { return get_rajce_url(); }
public string? get_username() { return host.get_config_string("username", null); }
private void set_username(string username) { host.set_config_string("username", username); }
- public string? get_token() { return host.get_config_string("token", null); }
- private void set_token(string? token) { host.set_config_string("token", token); }
+ public string? get_token() {
+ var user = get_username();
+ if (user == null)
+ return null;
+
+ try {
+ return Secret.password_lookup_sync(this.schema, null, "user", user);
+ } catch (Error err) {
+ critical("Failed to get token for user %s: %s", user, err.message);
+ }
+
+ return null;
+ }
+
+ private void set_token(string? token) {
+ var user = get_username();
+ if (user == null)
+ return;
+
+ try {
+ if (token == null || token == "") {
+ Secret.password_clear_sync(this.schema, null, "user", user);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (Rajce user %s)".printf(user),
+ token,
+ null,
+ "user", user);
+ }
+ } catch (Error err) {
+ critical("Failed to store token for user %s: %s", user, err.message);
+ }
+ }
// public int get_last_photo_size() { return host.get_config_int("last-photo-size", -1); }
// private void set_last_photo_size(int last_photo_size) { host.set_config_int("last-photo-size",
last_photo_size); }
public bool get_remember() { return host.get_config_bool("remember", false); }
diff --git a/plugins/shotwell-publishing-extras/YandexPublishing.vala
b/plugins/shotwell-publishing-extras/YandexPublishing.vala
index 2680df07..51bf2940 100644
--- a/plugins/shotwell-publishing-extras/YandexPublishing.vala
+++ b/plugins/shotwell-publishing-extras/YandexPublishing.vala
@@ -296,6 +296,7 @@ private class UploadTransaction: Transaction {
}
public class YandexPublisher : Spit.Publishing.Publisher, GLib.Object {
+ private const string PASSWORD_SCHEME = "org.gnome.Shotwell.Yandex";
private weak Spit.Publishing.PluginHost host = null;
private Spit.Publishing.ProgressCallback progress_reporter = null;
private weak Spit.Publishing.Service service = null;
@@ -310,6 +311,7 @@ public class YandexPublisher : Spit.Publishing.Publisher, GLib.Object {
private WebAuthPane web_auth_pane = null;
private Session session;
+ private Secret.Schema? schema = null;
public YandexPublisher(Spit.Publishing.Service service, Spit.Publishing.PluginHost host) {
this.service = service;
@@ -317,18 +319,36 @@ public class YandexPublisher : Spit.Publishing.Publisher, GLib.Object {
this.session = new Session();
this.album_list = new Gee.HashMap<string, string>();
this.options = new PublishOptions();
+ this.schema = new Secret.Schema (PASSWORD_SCHEME, Secret.SchemaFlags.NONE);
}
internal string? get_persistent_auth_token() {
- return host.get_config_string("auth_token", null);
+ try {
+ return Secret.password_lookup_sync(this.schema, null);
+ } catch (Error err) {
+ critical ("Failed to get api key for yandex: %s", err.message);
+ }
+
+ return null;
}
- internal void set_persistent_auth_token(string auth_token) {
- host.set_config_string("auth_token", auth_token);
+ internal void set_persistent_auth_token(string? auth_token) {
+ try {
+ if (auth_token == null | auth_token == "") {
+ Secret.password_clear_sync(this.schema, null);
+ } else {
+ Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT,
+ "Shotwell publishing (Yandex)",
+ auth_token,
+ null);
+ }
+ } catch (Error err) {
+ critical("Failed to store api key: %s", err.message);
+ }
}
internal void invalidate_persistent_session() {
- host.unset_config_key("auth_token");
+ set_persistent_auth_token(null);
}
internal bool is_persistent_session_available() {
diff --git a/plugins/shotwell-publishing-extras/meson.build b/plugins/shotwell-publishing-extras/meson.build
index 34f3e125..3f7845a6 100644
--- a/plugins/shotwell-publishing-extras/meson.build
+++ b/plugins/shotwell-publishing-extras/meson.build
@@ -11,7 +11,7 @@ shotwell_publishing_extra_resources = gnome.compile_resources('publishing-extra-
shared_module('shotwell-publishing-extras',
shotwell_publishing_extra_sources + shotwell_publishing_extra_resources,
dependencies : [gee, gtk, xml, soup, gdk_pixbuf, sw_plugin,
- sw_plugin_common_dep, json_glib, webkit],
+ sw_plugin_common_dep, json_glib, webkit, secret],
vala_args : [
'--gresources', 'org.gnome.Shotwell.Publishing.Extras.gresource.xml'
],
diff --git a/plugins/shotwell-publishing/PiwigoPublishing.vala
b/plugins/shotwell-publishing/PiwigoPublishing.vala
index 58d638e7..ce91e529 100644
--- a/plugins/shotwell-publishing/PiwigoPublishing.vala
+++ b/plugins/shotwell-publishing/PiwigoPublishing.vala
@@ -124,6 +124,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;
@@ -132,6 +134,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) {
@@ -139,6 +142,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
@@ -170,7 +176,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());
@@ -201,12 +209,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() {
@@ -309,7 +342,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());
@@ -359,10 +392,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);
@@ -1147,7 +1181,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]