diff --git a/Dockerfile.dev b/Dockerfile.dev index 1413edb..786190b 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,8 +1,7 @@ -FROM python:3-alpine +FROM python:3 WORKDIR /usr/src/panoptes-cli -RUN apk --no-cache add git RUN pip install git+git://github.com/zooniverse/panoptes-python-client.git COPY . . diff --git a/Dockerfile.dev2 b/Dockerfile.dev2 index 4a7399b..5a04833 100644 --- a/Dockerfile.dev2 +++ b/Dockerfile.dev2 @@ -1,8 +1,7 @@ -FROM python:2.7-alpine +FROM python:2.7 WORKDIR /usr/src/panoptes-cli -RUN apk --no-cache add git RUN pip install git+git://github.com/zooniverse/panoptes-python-client.git COPY . . diff --git a/Dockerfile.stable b/Dockerfile.stable index d489914..c2afdfe 100644 --- a/Dockerfile.stable +++ b/Dockerfile.stable @@ -1,4 +1,4 @@ -FROM python:3-alpine +FROM python:3 RUN pip install panoptescli diff --git a/Dockerfile.stable2 b/Dockerfile.stable2 index 9ecc3cd..c2eb168 100644 --- a/Dockerfile.stable2 +++ b/Dockerfile.stable2 @@ -1,4 +1,4 @@ -FROM python:2.7-alpine +FROM python:2.7 RUN pip install panoptescli diff --git a/panoptes_cli/commands/configure.py b/panoptes_cli/commands/configure.py index 51046d8..56aa548 100644 --- a/panoptes_cli/commands/configure.py +++ b/panoptes_cli/commands/configure.py @@ -1,5 +1,7 @@ -import click import os + +import click +import keyring import yaml from panoptes_cli.scripts.panoptes import cli @@ -25,12 +27,9 @@ def configure(ctx, edit_all): if opt == 'endpoint' and not edit_all: continue - is_password = opt == 'password' ctx.parent.config[opt] = click.prompt( opt, default=value, - hide_input=is_password, - show_default=not is_password, ) if not ctx.parent.config['endpoint'].startswith('https://'): @@ -38,6 +37,30 @@ def configure(ctx, edit_all): 'Error: Invalid endpoint supplied. Endpoint must be an HTTPS URL.' ) return -1 + + new_password = click.prompt( + 'Password [leave blank for no change]', + hide_input=True, + show_default=False, + default='', + ) + if new_password: + try: + keyring.set_password( + 'panoptes', + ctx.parent.config['username'], + new_password, + ) + except RuntimeError: + click.echo( + 'Warning: Could not save your password to the keyring. ' + 'You will be asked for your password each time.', + err=True, + ) + + save_config(ctx.parent.config_file, ctx.parent.config) + - with open(ctx.parent.config_file, 'w') as conf_f: - yaml.dump(ctx.parent.config, conf_f, default_flow_style=False) +def save_config(config_file, config): + with open(config_file, 'w') as conf_f: + yaml.dump(config, conf_f, default_flow_style=False) \ No newline at end of file diff --git a/panoptes_cli/commands/user.py b/panoptes_cli/commands/user.py index 31da83c..f135025 100644 --- a/panoptes_cli/commands/user.py +++ b/panoptes_cli/commands/user.py @@ -93,4 +93,4 @@ def token(): """ click.echo("Token: {}".format(Panoptes.client().get_bearer_token())) - click.echo("Expiry time: {}".format(Panoptes.client().bearer_expires)) \ No newline at end of file + click.echo("Expiry time: {}".format(Panoptes.client().bearer_expires)) diff --git a/panoptes_cli/scripts/panoptes.py b/panoptes_cli/scripts/panoptes.py index 2f96c1a..ba15fc7 100755 --- a/panoptes_cli/scripts/panoptes.py +++ b/panoptes_cli/scripts/panoptes.py @@ -1,6 +1,9 @@ -import click import os + +import click +import keyring import yaml + from panoptes_client import Panoptes @@ -28,7 +31,6 @@ def cli(ctx, endpoint, admin): ctx.config = { 'endpoint': 'https://www.zooniverse.org', 'username': '', - 'password': '', } try: @@ -41,10 +43,44 @@ def cli(ctx, endpoint, admin): ctx.config['endpoint'] = endpoint if ctx.invoked_subcommand != 'configure': + try: + password = keyring.get_password('panoptes', ctx.config['username']) + except RuntimeError: + password = None + + if 'password' in ctx.config: + if not password: + try: + password = ctx.config['password'] + keyring.set_password( + 'panoptes', + ctx.config['username'], + password, + ) + retrieved_password = keyring.get_password( + 'panoptes', + ctx.config['username'], + ) + + del ctx.config['password'] + save_config(ctx.config_file, ctx.config) + except RuntimeError: + click.echo( + 'Warning: Your password is stored insecurely and ' + 'secure keyrings are not supported on your system.', + err=True, + ) + + if not password: + password = click.prompt( + 'Password for {}'.format(ctx.config['username']), + hide_input=True, + ) + Panoptes.connect( endpoint=ctx.config['endpoint'], username=ctx.config['username'], - password=ctx.config['password'], + password=password, admin=admin, ) diff --git a/setup.py b/setup.py index 6543159..db86a37 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ 'panoptes-client>=1.0,<2.0', 'humanize>=0.5.1,<0.6', 'pathvalidate>=0.29.0,<0.30', + 'keyring>=19.2,<19.3', ], entry_points=''' [console_scripts]