aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/src/meshbay_cli/commands/login.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-cli/src/meshbay_cli/commands/login.py')
-rw-r--r--packages/meshbay-cli/src/meshbay_cli/commands/login.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/packages/meshbay-cli/src/meshbay_cli/commands/login.py b/packages/meshbay-cli/src/meshbay_cli/commands/login.py
new file mode 100644
index 0000000..cbd16ef
--- /dev/null
+++ b/packages/meshbay-cli/src/meshbay_cli/commands/login.py
@@ -0,0 +1,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
+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 sys.stdin.isatty():
+ 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