[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.
This commit is contained in:
Fabio Manganiello 2024-01-18 23:48:28 +01:00
parent 31de917631
commit e022712b7b
2 changed files with 16 additions and 19 deletions

View file

@ -90,12 +90,9 @@ class GooglePlugin(Plugin):
if self._scopes: if self._scopes:
scopes = " ".join(sorted(self._scopes)) scopes = " ".join(sorted(self._scopes))
try:
self.credentials = { self.credentials = {
scopes: get_credentials(scopes, secrets_file=self._secrets_path) scopes: get_credentials(scopes, secrets_file=self._secrets_path)
} }
except AssertionError as e:
self.logger.warning(str(e))
else: else:
self.credentials = {} self.credentials = {}

View file

@ -63,21 +63,17 @@ def get_credentials(scope: str, secrets_file: Optional[str] = None):
not os.path.isfile(credentials_file) not os.path.isfile(credentials_file)
and secrets_file and secrets_file
and os.path.isfile(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. args = []
# 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 []
)
generate_credentials(secrets_file, scope, *args) generate_credentials(secrets_file, scope, *args)
assert os.path.isfile(credentials_file), tw.dedent( assert os.path.isfile(credentials_file), tw.dedent(
f""" f"""
Credentials file {credentials_file} not found. Generate it through: Credentials file {credentials_file} not found. Generate it through:
python -m platypush.plugins.google.credentials "{','.join(scopes)}" /path/to/client_secret.json python -m platypush.plugins.google.credentials "{','.join(scopes)}" {
secrets_file or '/path/to/client_secret.json'
}
[--auth_host_name AUTH_HOST_NAME] [--auth_host_name AUTH_HOST_NAME]
[--noauth_local_webserver] [--noauth_local_webserver]
[--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]] [--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]
@ -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 flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args(args) # type: ignore
tools.run_flow(flow, store, flags) tools.run_flow(flow, store, flags)
print("Storing credentials to", credentials_file) 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(): def main():