From 7868ff68cff97b21fe6d8681f8bc0334849c4d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 9 Jun 2025 10:49:17 +0200 Subject: New upstream version 0.32.13 --- .../shotwell/GoogleAuthenticator.vala | 35 ++++++++++++++-------- .../shotwell/ShotwellAuthenticatorFactory.vala | 4 +-- 2 files changed, 25 insertions(+), 14 deletions(-) (limited to 'plugins/authenticator') diff --git a/plugins/authenticator/shotwell/GoogleAuthenticator.vala b/plugins/authenticator/shotwell/GoogleAuthenticator.vala index 5a0d934..1fe2448 100644 --- a/plugins/authenticator/shotwell/GoogleAuthenticator.vala +++ b/plugins/authenticator/shotwell/GoogleAuthenticator.vala @@ -64,7 +64,7 @@ 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 string[] scopes = null; // Prepare for multiple user accounts private string accountname = "default"; @@ -74,12 +74,12 @@ namespace Publishing.Authenticator.Shotwell.Google { private string welcome_message = null; private Secret.Schema? schema = null; - public Google(string scope, + public Google(string[] scopes, string welcome_message, Spit.Publishing.PluginHost host) { this.host = host; this.params = new GLib.HashTable(str_hash, str_equal); - this.scope = scope; + this.scopes = scopes; this.session = new Session(); this.welcome_message = welcome_message; this.schema = new Secret.Schema(PASSWORD_SCHEME, Secret.SchemaFlags.NONE, @@ -93,7 +93,7 @@ namespace Publishing.Authenticator.Shotwell.Google { try { refresh_token = Secret.password_lookup_sync(this.schema, null, SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(), - SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", this.scope); + SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", get_scopes()); } catch (Error err) { critical("Failed to lookup refresh_token from password store: %s", err.message); } @@ -106,6 +106,10 @@ namespace Publishing.Authenticator.Shotwell.Google { this.do_show_service_welcome_pane(); } + public string get_scopes(string separator=",") { + return string.joinv(separator, this.scopes); + } + public bool can_logout() { return true; } @@ -119,9 +123,9 @@ namespace Publishing.Authenticator.Shotwell.Google { try { Secret.password_clear_sync(this.schema, null, SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(), - SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", this.scope); + SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", get_scopes()); } catch (Error err) { - critical("Failed to remove password for scope %s: %s", this.scope, err.message); + critical("Failed to remove password for scope %s: %s", get_scopes(), err.message); } } @@ -147,7 +151,7 @@ namespace Publishing.Authenticator.Shotwell.Google { "response_type=code&" + "client_id=" + OAUTH_CLIENT_ID + "&" + "redirect_uri=" + GLib.Uri.escape_string(OAUTH_CALLBACK_URI, null) + "&" + - "scope=" + GLib.Uri.escape_string(this.scope, null) + "+" + + "scope=" + GLib.Uri.escape_string(get_scopes(" "), null) + "+" + GLib.Uri.escape_string("https://www.googleapis.com/auth/userinfo.profile", null) + "&" + "state=connect&" + "access_type=offline&" + @@ -155,18 +159,25 @@ namespace Publishing.Authenticator.Shotwell.Google { var auth_callback = new AuthCallback(); string? web_auth_code = null; + auth_callback.auth.connect((prm) => { if ("code" in prm) { web_auth_code = prm["code"]; } + if ("scope" in prm) { + debug("Effective scopes as returned from login: %s", prm["scope"]); + } do_hosted_web_authentication.callback(); }); host.register_auth_callback(REVERSE_CLIENT_ID, auth_callback); try { + debug("Launching external authentication on URI %s", user_authorization_url); AppInfo.launch_default_for_uri(user_authorization_url, null); host.install_login_wait_pane(); yield; + // FIXME throw error missing scopes + yield do_get_access_tokens(web_auth_code); } catch (Error err) { host.post_error(err); @@ -315,12 +326,12 @@ namespace Publishing.Authenticator.Shotwell.Google { assert(session.is_authenticated()); try { Secret.password_store_sync(this.schema, Secret.COLLECTION_DEFAULT, - "Shotwell publishing (Google account scope %s@%s)".printf(this.accountname, this.scope), + "Shotwell publishing (Google account scope %s@%s)".printf(this.accountname, get_scopes()), session.refresh_token, null, SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(), - SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", this.scope); + SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", get_scopes()); } catch (Error err) { - critical("Failed to look up password for scope %s: %s", this.scope, err.message); + critical("Failed to look up password for scope %s: %s", get_scopes(), err.message); } this.authenticated(); @@ -352,9 +363,9 @@ namespace Publishing.Authenticator.Shotwell.Google { try { Secret.password_clear_sync(this.schema, null, SCHEMA_KEY_PROFILE_ID, host.get_current_profile_id(), - SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", this.scope); + SCHEMA_KEY_ACCOUNTNAME, this.accountname, "scope", get_scopes()); } catch (Error err) { - critical("Failed to remove password for accountname@scope %s@%s: %s", this.accountname, this.scope, err.message); + critical("Failed to remove password for accountname@scope %s@%s: %s", this.accountname, get_scopes(), err.message); } Idle.add (() => { this.authenticate(); return false; }); diff --git a/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala b/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala index 01fa3c3..c289006 100644 --- a/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala +++ b/plugins/authenticator/shotwell/ShotwellAuthenticatorFactory.vala @@ -27,11 +27,11 @@ namespace Publishing.Authenticator { case "flickr": return new Shotwell.Flickr.Flickr(host); case "youtube": - return new Shotwell.Google.Google("https://www.googleapis.com/auth/youtube", _("You are not currently logged into YouTube.\n\nYou must have already signed up for a Google account and set it up for use with YouTube to continue. You can set up most accounts by using your browser to log into the YouTube site at least once.\n\nShotwell uses the YouTube API services https://developers.google.com/youtube for accessing your YouTube channel and upload the videos. By using Shotwell to access YouTube, you agree to be bound to the YouTube Terms of Service as available at https://www.youtube.com/t/terms\n\nShotwell's privacy policy regarding the use of data related to your Google account in general and YouTube in particular can be found in our online services privacy policy\n\nFor Google's own privacy policy, please refer to https://policies.google.com/privacy"), host); + return new Shotwell.Google.Google({"https://www.googleapis.com/auth/youtube"}, _("You are not currently logged into YouTube.\n\nYou must have already signed up for a Google account and set it up for use with YouTube to continue. You can set up most accounts by using your browser to log into the YouTube site at least once.\n\nShotwell uses the YouTube API services https://developers.google.com/youtube for accessing your YouTube channel and upload the videos. By using Shotwell to access YouTube, you agree to be bound to the YouTube Terms of Service as available at https://www.youtube.com/t/terms\n\nShotwell's privacy policy regarding the use of data related to your Google account in general and YouTube in particular can be found in our online services privacy policy\n\nFor Google's own privacy policy, please refer to https://policies.google.com/privacy"), host); case "tumblr": return new Shotwell.Tumblr.Tumblr(host); case "google-photos": - return new Shotwell.Google.Google("https://www.googleapis.com/auth/photoslibrary", _("You are not currently logged into Google Photos.\n\nYou must have already signed up for a Google account and set it up for use with Google Photos. Shotwell uses the Google Photos API services https://developers.google.com/photos/ for all interaction with your Google Photos data. You will have to grant access Shotwell to your Google Photos library.\n\nShotwell's privacy policy regarding the use of data related to your Google account in general and Google Photos in particular can be found in our online services privacy policy. For Google's own privacy policy, please refer to https://policies.google.com/privacy"), host); + return new Shotwell.Google.Google({"https://www.googleapis.com/auth/photoslibrary.appendonly", "https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata"}, _("You are not currently logged into Google Photos.\n\nYou must have already signed up for a Google account and set it up for use with Google Photos. Shotwell uses the Google Photos API services https://developers.google.com/photos/ for all interaction with your Google Photos data. You will have to grant access Shotwell to your Google Photos library.\n\nShotwell's privacy policy regarding the use of data related to your Google account in general and Google Photos in particular can be found in our online services privacy policy. For Google's own privacy policy, please refer to https://policies.google.com/privacy"), host); default: return null; } -- cgit v1.2.3