From 6b89ede0919d2f2cb4cc05dd54b36347bff4de25 Mon Sep 17 00:00:00 2001
From: Fabio Manganiello <fabio@manganiello.tech>
Date: Thu, 18 Jan 2024 23:48:28 +0100
Subject: [PATCH] [Google] Updated authorization flow for Google plugins.

The new authorization flow also requires the user to input a code
returned on the browser's authorization page.

Since the Google authentication libraries seem to use a simple `input()`
to read this code, things are likely to fail quite badly if Platypush is
run in non-interactive mode - e.g. through a systemd service or in a
Docker container.

Thus we need to go with Google's automatic flow only if `DISPLAY` or
`BROWSER` are set (thus the interactive flow can proceed), and throw an
`AssertionError` with the command to execute if no display/browser are
detected.
---
 platypush/plugins/google/__init__.py    |  9 +++------
 platypush/plugins/google/credentials.py | 26 ++++++++++++-------------
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/platypush/plugins/google/__init__.py b/platypush/plugins/google/__init__.py
index 95a6569a..a35d1f4b 100644
--- a/platypush/plugins/google/__init__.py
+++ b/platypush/plugins/google/__init__.py
@@ -90,12 +90,9 @@ class GooglePlugin(Plugin):
 
         if self._scopes:
             scopes = " ".join(sorted(self._scopes))
-            try:
-                self.credentials = {
-                    scopes: get_credentials(scopes, secrets_file=self._secrets_path)
-                }
-            except AssertionError as e:
-                self.logger.warning(str(e))
+            self.credentials = {
+                scopes: get_credentials(scopes, secrets_file=self._secrets_path)
+            }
         else:
             self.credentials = {}
 
diff --git a/platypush/plugins/google/credentials.py b/platypush/plugins/google/credentials.py
index a7388820..80f8a3a5 100644
--- a/platypush/plugins/google/credentials.py
+++ b/platypush/plugins/google/credentials.py
@@ -63,25 +63,21 @@ def get_credentials(scope: str, secrets_file: Optional[str] = None):
         not os.path.isfile(credentials_file)
         and secrets_file
         and os.path.isfile(secrets_file)
+        and (os.getenv("DISPLAY") or os.getenv("BROWSER"))
     ):
-        # If DISPLAY or BROWSER are set, then we can open the authentication URL in the browser.
-        # Otherwise, we'll have to use the --noauth_local_webserver flag and copy/paste the URL
-        args = (
-            ["--noauth_local_webserver"]
-            if not (os.getenv("DISPLAY") or os.getenv("BROWSER"))
-            else []
-        )
-
+        args = []
         generate_credentials(secrets_file, scope, *args)
 
     assert os.path.isfile(credentials_file), tw.dedent(
         f"""
         Credentials file {credentials_file} not found. Generate it through:
-            python -m platypush.plugins.google.credentials "{','.join(scopes)}" /path/to/client_secret.json
-                [--auth_host_name AUTH_HOST_NAME]
-                [--noauth_local_webserver]
-                [--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]
-                [--logging_level [DEBUG,INFO,WARNING,ERROR,CRITICAL]]
+            python -m platypush.plugins.google.credentials "{','.join(scopes)}" {
+                secrets_file or '/path/to/client_secret.json'
+            }
+              [--auth_host_name AUTH_HOST_NAME]
+              [--noauth_local_webserver]
+              [--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]
+              [--logging_level [DEBUG,INFO,WARNING,ERROR,CRITICAL]]
 
         Specify --noauth_local_webserver if you're running this script on a headless machine.
         You will then get an authentication URL on the logs.
@@ -112,6 +108,10 @@ def generate_credentials(client_secret_path: str, scope: str, *args: str):
     flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args(args)  # type: ignore
     tools.run_flow(flow, store, flags)
     print("Storing credentials to", credentials_file)
+    print(
+        "\nIf this is not the working directory of your Platypush instance, \n"
+        "then move the generated credentials file to WORKDIR/credentials/google"
+    )
 
 
 def main():