diff libervia/cli/cmd_account.py @ 4075:47401850dec6

refactoring: rename `libervia.frontends.jp` to `libervia.cli`
author Goffi <goffi@goffi.org>
date Fri, 02 Jun 2023 14:54:26 +0200
parents libervia/frontends/jp/cmd_account.py@26b7ed2817da
children 0d7bb4df2343
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libervia/cli/cmd_account.py	Fri Jun 02 14:54:26 2023 +0200
@@ -0,0 +1,253 @@
+#!/usr/bin/env python3
+
+
+# Libervia CLI
+# Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""This module permits to manage XMPP accounts using in-band registration (XEP-0077)"""
+
+from libervia.cli.constants import Const as C
+from libervia.frontends.bridge.bridge_frontend import BridgeException
+from libervia.backend.core.log import getLogger
+from libervia.backend.core.i18n import _
+from libervia.cli import base
+from libervia.frontends.tools import jid
+
+
+log = getLogger(__name__)
+
+__commands__ = ["Account"]
+
+
+class AccountCreate(base.CommandBase):
+    def __init__(self, host):
+        super(AccountCreate, self).__init__(
+            host,
+            "create",
+            use_profile=False,
+            use_verbose=True,
+            help=_("create a XMPP account"),
+        )
+
+    def add_parser_options(self):
+        self.parser.add_argument(
+            "jid", help=_("jid to create")
+        )
+        self.parser.add_argument(
+            "password", help=_("password of the account")
+        )
+        self.parser.add_argument(
+            "-p",
+            "--profile",
+            help=_(
+                "create a profile to use this account (default: don't create profile)"
+            ),
+        )
+        self.parser.add_argument(
+            "-e",
+            "--email",
+            default="",
+            help=_("email (usage depends of XMPP server)"),
+        )
+        self.parser.add_argument(
+            "-H",
+            "--host",
+            default="",
+            help=_("server host (IP address or domain, default: use localhost)"),
+        )
+        self.parser.add_argument(
+            "-P",
+            "--port",
+            type=int,
+            default=0,
+            help=_("server port (default: {port})").format(
+                port=C.XMPP_C2S_PORT
+            ),
+        )
+
+    async def start(self):
+        try:
+            await self.host.bridge.in_band_account_new(
+                self.args.jid,
+                self.args.password,
+                self.args.email,
+                self.args.host,
+                self.args.port,
+            )
+
+        except BridgeException as e:
+            if e.condition == 'conflict':
+                self.disp(
+                    f"The account {self.args.jid} already exists",
+                    error=True
+                )
+                self.host.quit(C.EXIT_CONFLICT)
+            else:
+                self.disp(
+                    f"can't create account on {self.args.host or 'localhost'!r} with jid "
+                    f"{self.args.jid!r} using In-Band Registration: {e}", error=True)
+                self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        except Exception as e:
+            self.disp(f"Internal error: {e}", error=True)
+            self.host.quit(C.EXIT_INTERNAL_ERROR)
+
+        self.disp(_("XMPP account created"), 1)
+
+        if self.args.profile is None:
+            self.host.quit()
+
+
+        self.disp(_("creating profile"), 2)
+        try:
+            await self.host.bridge.profile_create(
+                self.args.profile,
+                self.args.password,
+                "",
+            )
+        except BridgeException as e:
+            if e.condition == 'conflict':
+                self.disp(
+                    f"The profile {self.args.profile} already exists",
+                    error=True
+                )
+                self.host.quit(C.EXIT_CONFLICT)
+            else:
+                self.disp(
+                    _("Can't create profile {profile} to associate with jid "
+                      "{jid}: {e}").format(
+                          profile=self.args.profile,
+                          jid=self.args.jid,
+                          e=e
+                      ),
+                    error=True,
+                )
+                self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        except Exception as e:
+            self.disp(f"Internal error: {e}", error=True)
+            self.host.quit(C.EXIT_INTERNAL_ERROR)
+
+        self.disp(_("profile created"), 1)
+        try:
+            await self.host.bridge.profile_start_session(
+                self.args.password,
+                self.args.profile,
+            )
+        except Exception as e:
+            self.disp(f"can't start profile session: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        try:
+            await self.host.bridge.param_set(
+                "JabberID",
+                self.args.jid,
+                "Connection",
+                profile_key=self.args.profile,
+            )
+        except Exception as e:
+            self.disp(f"can't set JabberID parameter: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        try:
+            await self.host.bridge.param_set(
+                "Password",
+                self.args.password,
+                "Connection",
+                profile_key=self.args.profile,
+            )
+        except Exception as e:
+            self.disp(f"can't set Password parameter: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        self.disp(
+            f"profile {self.args.profile} successfully created and associated to the new "
+            f"account", 1)
+        self.host.quit()
+
+
+class AccountModify(base.CommandBase):
+    def __init__(self, host):
+        super(AccountModify, self).__init__(
+            host, "modify", help=_("change password for XMPP account")
+        )
+
+    def add_parser_options(self):
+        self.parser.add_argument(
+            "password", help=_("new XMPP password")
+        )
+
+    async def start(self):
+        try:
+            await self.host.bridge.in_band_password_change(
+                self.args.password,
+                self.args.profile,
+            )
+        except Exception as e:
+            self.disp(f"can't change XMPP password: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+        else:
+            self.host.quit()
+
+
+class AccountDelete(base.CommandBase):
+    def __init__(self, host):
+        super(AccountDelete, self).__init__(
+            host, "delete", help=_("delete a XMPP account")
+        )
+
+    def add_parser_options(self):
+        self.parser.add_argument(
+            "-f",
+            "--force",
+            action="store_true",
+            help=_("delete account without confirmation"),
+        )
+
+    async def start(self):
+        try:
+            jid_str = await self.host.bridge.param_get_a_async(
+                "JabberID",
+                "Connection",
+                profile_key=self.profile,
+            )
+        except Exception as e:
+            self.disp(f"can't get JID of the profile: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        jid_ = jid.JID(jid_str)
+        if not self.args.force:
+            message = (
+                f"You are about to delete the XMPP account with jid {jid_!r}\n"
+                f"This is the XMPP account of profile {self.profile!r}\n"
+                f"Are you sure that you want to delete this account?"
+            )
+            await self.host.confirm_or_quit(message, _("Account deletion cancelled"))
+
+        try:
+            await self.host.bridge.in_band_unregister(jid_.domain, self.args.profile)
+        except Exception as e:
+            self.disp(f"can't delete XMPP account with jid {jid_!r}: {e}", error=True)
+            self.host.quit(C.EXIT_BRIDGE_ERRBACK)
+
+        self.host.quit()
+
+
+class Account(base.CommandBase):
+    subcommands = (AccountCreate, AccountModify, AccountDelete)
+
+    def __init__(self, host):
+        super(Account, self).__init__(
+            host, "account", use_profile=False, help=("XMPP account management")
+        )