diff --git a/frappe/commands/site.py b/frappe/commands/site.py index ab599be121..eb5a732f04 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -496,6 +496,32 @@ def add_system_manager(context, email, first_name, last_name, send_welcome_email raise SiteNotSpecifiedError +@click.command("add-user") +@click.argument("email") +@click.option("--first-name") +@click.option("--last-name") +@click.option("--password") +@click.option("--user-type") +@click.option("--add-role", multiple=True) +@click.option("--send-welcome-email", default=False, is_flag=True) +@pass_context +def add_user_for_sites( + context, email, first_name, last_name, user_type, send_welcome_email, password, add_role +): + "Add user to a site" + import frappe.utils.user + + for site in context.sites: + frappe.connect(site=site) + try: + add_new_user(email, first_name, last_name, user_type, send_welcome_email, password, add_role) + frappe.db.commit() + finally: + frappe.destroy() + if not context.sites: + raise SiteNotSpecifiedError + + @click.command("disable-user") @click.argument("email") @pass_context @@ -1275,8 +1301,38 @@ def handle_data(data: dict, format="json"): render_table(data) +def add_new_user( + email, + first_name=None, + last_name=None, + user_type="System User", + send_welcome_email=False, + password=None, + role=None, +): + user = frappe.new_doc("User") + user.update( + { + "name": email, + "email": email, + "enabled": 1, + "first_name": first_name or email, + "last_name": last_name, + "user_type": user_type, + "send_welcome_email": 1 if send_welcome_email else 0, + } + ) + user.insert() + user.add_roles(*role) + if password: + from frappe.utils.password import update_password + + update_password(user=user.name, pwd=password) + + commands = [ add_system_manager, + add_user_for_sites, backup, drop_site, install_app, diff --git a/frappe/tests/test_commands.py b/frappe/tests/test_commands.py index c605a1a056..898b696c8d 100644 --- a/frappe/tests/test_commands.py +++ b/frappe/tests/test_commands.py @@ -691,6 +691,18 @@ class TestSiteMigration(BaseTestCommands): self.assertEqual(result.exception, None) +class TestAddNewUser(BaseTestCommands): + def test_create_user(self): + self.execute( + "bench --site {site} add-user test@gmail.com --first-name test --last-name test --password 123 --user-type 'System User' --add-role 'Accounts User' --add-role 'Sales User'" + ) + frappe.db.rollback() + self.assertEqual(self.returncode, 0) + user = frappe.get_doc("User", "test@gmail.com") + roles = {r.role for r in user.roles} + self.assertEqual({"Accounts User", "Sales User"}, roles) + + class TestBenchBuild(BaseTestCommands): def test_build_assets_size_check(self): with cli(frappe.commands.utils.build, "--force --production") as result: