aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/src/meshbay_cli/commands/login.py
blob: f26691c1a69864c09ea47403820d21ede5dc068e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
"""`login`: sign in with the passphrase, and remember the session."""

import contextlib
import json
import sys

from ..client.account import Account
from ..client.groups import my_groups
from ..client.store import FILE_KEY_NOTICE, KEY_FILE
from ..errors import USAGE, CliError
from ..output import err, safe, sentence, terminal
from .context import Context
from .logout import sign_out_stored

HELP = "sign in, and remember the session so later runs need no passphrase"


def add_parser(sub, parent) -> None:
    p = sub.add_parser("login", parents=[parent], help=HELP, description=sentence(HELP) + ".")
    p.add_argument("--no-remember", action="store_true",
                   help="check the credentials and store nothing")


async def run(ctx: Context) -> int:
    username = ctx.username or ctx.stored_username
    if not username:
        if not terminal(sys.stdin):
            raise CliError(USAGE, "Name the account with --user.")
        username = input("Username: ").strip()
        ctx.username = username
    if not username:
        raise CliError(USAGE, "No username given.")
    ctx.username = username

    notice = await ctx.hub.check_version()
    remember = not ctx.args.no_remember

    # Signing in again as the same account keeps its device key, its node
    # identities and its pins; another account replaces the store.
    previous = ctx.store.peek()
    account = Account(ctx.hub, username, ctx.passphrase)
    if previous.get("hub") == ctx.hub.url and previous.get("username") == username:
        with contextlib.suppress(CliError):
            ctx.store.load()
            account.state, account.secrets = ctx.store.state, ctx.store.secrets
    elif remember and previous:
        await sign_out_stored(ctx)

    await account.sign_in(remember=remember)
    groups = await my_groups(account)

    if remember:
        kind = await account.remember(ctx.store)
        if kind == KEY_FILE:
            err(FILE_KEY_NOTICE)
    else:
        await account.close()

    n = len(groups)
    if ctx.args.json:
        print(json.dumps({"username": username, "hub": ctx.hub.url, "groups": n,
                          "remembered": remember,
                          "key_store": ctx.store.peek().get("key_store") if remember
                          else None}))
    else:
        verb = "Signed in" if remember else "Credentials accepted"
        print(f"{verb}: {safe(username)} on {ctx.hub.url} — "
              f"{n} group{'s' if n != 1 else ''}.")
    if notice:
        err(notice)
    return 0