From 35ff892db15dfad4f464002309e28da8af1d0e5b Mon Sep 17 00:00:00 2001 From: Blallo Date: Thu, 7 Feb 2019 12:02:42 +0100 Subject: [PATCH] Adding login/logout subcommands. --- bot_z/cli.py | 101 ++++++++++++++++++++++++++++++++++++++++++++++- bot_z/zdaemon.py | 10 ++++- 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/bot_z/cli.py b/bot_z/cli.py index 09de09f..996839f 100644 --- a/bot_z/cli.py +++ b/bot_z/cli.py @@ -3,6 +3,7 @@ """Console script to control the bot_z daemon""" import errno +from getpass import getpass import logging import os import sys @@ -36,7 +37,11 @@ def _check_name(lifo_path: str, name: T.Optional[str]) -> str: @click.group() @click.option("-d", "--debug", is_flag=True, default=False, help="Enable debug mode.") @click.option( - "--headless", is_flag=True, default=True, help="Start the clients in headless mode." + "--no-headless", + "headless", + is_flag=True, + default=True, + help="Start the clients in foreground.", ) @click.option( "-v", @@ -212,6 +217,100 @@ def stop_command(ctx: click.Context, name: T.Optional[str]) -> None: logger.info("Stop sent.") +def prompt_for_creds(param: str, hidden: bool = False) -> str: + if hidden: + return getpass("Insert {}: ".format(param)) + return input("Insert {}: ".format(param)) + + +@cli.command("login") +@click.option("-n", "--name", default=None, help="The instance to interact with.") +@click.option( + "-c", + "--credfile", + default=None, + type=click.File(), + help="The file containing username and password, on one line each.", +) +@click.option("-u", "--username", default=None, help="The username to login with.") +@click.option( + "-p", + "--password", + default=None, + help="[USE ONLY WHEN DEBUGGING!] The password to login with. Use --credfile.", +) +@click.option( + "-f", + "--force", + is_flag=True, + default=False, + help="Force logout, bypass login check.", +) +@click.pass_context +def login_command( + ctx: click.Context, + name: T.Optional[str], + username: T.Optional[str], + password: T.Optional[str], + credfile: T.Optional[T.TextIO], + force: bool, +) -> None: + """ + Writes on the fifo. Invokes the stop. + """ + no_userpass = username is None or password is None + if credfile is not None and no_userpass: + username = credfile.readline() + password = credfile.readline() + elif credfile is not None and not no_userpass: + logger.warning("Ignoring command line provided username and password.") + elif credfile is None and no_userpass: + logger.warning("Missing username or password and credfile.") + if username is None: + username = prompt_for_creds("username") + if password is None: + password = prompt_for_creds("password", hidden=True) + else: + logger.warning("Do not use command line provided password in production!") + + logger.debug("Sending the login command down the pipe: %s", ctx.obj["fifo"]) + name = _check_name(ctx.obj["lifo"], name) + logging.info('Logging in on instance "%s" with username "%s".', name, username) + with open(ctx.obj["fifo"], "w") as fifo: + fifo.write( + cmd_marshal( + name=name, + cmd="login", + username=username, + password=password, + force=force, + ) + ) + logger.info("Login sent.") + + +@cli.command("logout") +@click.option("-n", "--name", default=None, help="The instance to interact with.") +@click.option( + "-f", + "--force", + is_flag=True, + default=False, + help="Force logout, bypass login check.", +) +@click.pass_context +def logout_command(ctx: click.Context, name: T.Optional[str], force: bool) -> None: + """ + Writes on the fifo. Invokes the stop. + """ + logger.debug("Sending the logout command down the pipe: %s", ctx.obj["fifo"]) + name = _check_name(ctx.obj["lifo"], name) + logging.info("Logging out on instance: %s", name) + with open(ctx.obj["fifo"], "w") as fifo: + fifo.write(cmd_marshal(name=name, cmd="logout", force=force)) + logger.info("Logout sent.") + + @cli.command("reload") @click.option("-n", "--name", default=None, help="The instance to interact with.") @click.pass_context diff --git a/bot_z/zdaemon.py b/bot_z/zdaemon.py index a5e7cd8..ea30edc 100644 --- a/bot_z/zdaemon.py +++ b/bot_z/zdaemon.py @@ -117,12 +117,12 @@ def operator_login(op: Operator, username: str, password: str, force: bool) -> N logger.info("Login done.") -def operator_logout(op: Operator, username: str, force: bool) -> None: +def operator_logout(op: Operator, force: bool) -> None: """ Instructs the operator to perform logout. """ logger.debug("Performing logout.") - op.logout(username, password, force) + op.logout(force) logger.info("Logout done.") @@ -234,6 +234,12 @@ def listen_client( logger.debug("Status: %s", status) with Fifo(cmd["rfifo_path"], "w") as rfifo: rfifo.write(cmd_marshal(name=cmd["name"], cmd=status)) + elif cmd["cmd"] == "login": + logger.debug("Received command: login") + cmd_map["login"](op, cmd["username"], cmd["password"], cmd["force"]) + elif cmd["cmd"] == "logout": + logger.debug("Received command: logout") + cmd_map["logout"](op, cmd["force"]) def listen_commands(