From e022712b7b5e37c6a1a2bf115ca2fb8759d80c03 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello 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 95a6569af..a35d1f4b3 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 a7388820c..80f8a3a50 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():