#!/usr/bin/python3
import sys
import os
import socket
import subprocess
import syslog

import mini_buildd.cli
import mini_buildd.net

#: Needed for man page hack in setup.py
DESCRIPTION = "Script to use as a 'command' in an authorized_key file to allow mini-buildd-api runs only via SSH."
EPILOG = """
You may use this to authorize certain roles (for now: superuser and
staff) via plain secure SSH.

Steps to install:

As user 'root'::

  adduser --disabled-password mini-buildd-admin
  adduser --disabled-password mini-buildd-staff
  # OPTIONAL: Allows 'auth log' with the fingerprint
  adduser mini-buildd-admin adm
  adduser mini-buildd-staff adm

As mini-buildd-[staff|uploader]::

  Set up ~/.dput.cf with exactly one mini-buildd target.
  Configure python-keyring to use a plaintext keyring, see "/usr/share/doc/mini-buildd/examples/keyringrc.cfg"
  Run once to save the password:
   $ mini-buildd-api admin|staff@TARGET status

As admin user at the mini-buildd instance (web app)::

  Generate appropriate django pseudo users ("admin" does already exist).

To authorize a SSH Key, as user mini-buildd-uploader, add a line like this::

  command="/usr/sbin/mini-buildd-ssh-client-command" ssh-rsa AA...

per ssh user key.

As SSH user::

  Run 'ssh mini-buildd-[admin|staff]@your.host.name mini-buildd-api -x -z -y
"""

# Use syslog, facility user, to log access and key
syslog.openlog(facility=syslog.LOG_USER)


def log(*args):
    print(*args, file=sys.stderr)


class CLI(mini_buildd.cli.CLI):
    def __init__(self):
        self.dputcf = mini_buildd.cli.DputCf()

        super().__init__("mini-buildd-ssh-client-command", DESCRIPTION, epilog=EPILOG)

    def runcli(self):
        retval = 0
        try:
            user = os.getenv("USER")  # mini-buildd-admin, mini-buildd-staff, mini-buildd-uploader
            dummy0, dummy1, mbd_user = user.rpartition("-")
            mbd_endpoint = mini_buildd.net.ClientEndpoint(mini_buildd.cli.DputCf().first_http_url())
            mbd_endpoint.user = mbd_user
            mbd_target = mbd_endpoint.geturl(with_user=True)

            # Build up secure command to use from original command
            original_command = os.environ.get("SSH_ORIGINAL_COMMAND", "").split()
            log("I: Original command: ", original_command)
            if not original_command or original_command[0] != "mini-buildd-api":
                raise Exception("You may only run mini-buildd-api here.")
            command = ["mini-buildd-api", original_command[1:], mbd_target] + original_command[2:]

            # Run command
            log("I: Running: ", command)
            log("N: Some commands (like migrate) need a confirmation (but you will not see the prompt here).")
            log("N: You may of course use '--auto-confirm' directly to avoid the confirmation.")
            log(f"N: IN CASE THIS STALLS HERE: Type '{original_command[1]}<RETURN>' to continue.")
            log("---mini-buildd-api---")
            subprocess.check_call(command)

            # Try to do the auth log
            mini_buildd.cli.auth_log("SUCCESS")

        except BaseException as e:
            mini_buildd.cli.auth_log("FAILED")
            identity = mbd_target[12:]
            mu = mbd_user

            log(f"""\
----------------------------------------------------------------------
*ERROR*: {e}

You can only call me like this:

 $ ssh {os.getenv("USER")}@{socket.getfqdn()} mini-buildd-api [OPTIONS W/O ENDPOINT...]

It's recommended to update your shell config like so:

 alias mbdt-{identity}-{mu}="ssh {os.getenv("USER")}@{socket.getfqdn()} mini-buildd-api"

Examples (using sandbox repo "test"; see 'mini-buildd-api --help'):

 $ mbdt-{identity}-{mu} migrate PACKAGE wheezy-test-unstable                            # (staff) Migrate a package to testing
 $ mbdt-{identity}-{mu} migrate PACKAGE wheezy-test-testing                             # (staff) Migrate a package to stable
 $ mbdt-{identity}-{mu} port_ext http://.../PACKAGE_0.0.5.dsc wheezy-test-experimental  # (staff) External port to experimental
 $ mbdt-{identity}-{mu} start|stop                                                      # (superuser) Start/stop mini-buildd
    """)
            retval = 1

        sys.exit(retval)


CLI().run()
