import argparse import sys from typing import Any from django.core import validators from django.core.exceptions import ValidationError from django.core.management.base import CommandError from django.db.utils import IntegrityError from zerver.lib.actions import do_create_user from zerver.lib.initial_password import initial_password from zerver.lib.management import ZulipBaseCommand class Command(ZulipBaseCommand): help = """Create the specified user with a default initial password. Set tos_version=None, so that the user needs to do a ToS flow on login. Omit both and for interactive user creation. """ def add_arguments(self, parser: argparse.ArgumentParser) -> None: parser.add_argument( "--this-user-has-accepted-the-tos", dest="tos", action="store_true", help="Acknowledgement that the user has already accepted the ToS.", ) parser.add_argument( "--password", help="password of new user. For development only." "Note that we recommend against setting " "passwords this way, since they can be snooped by any user account " "on the server via `ps -ef` or by any superuser with" "read access to the user's bash history.", ) parser.add_argument( "--password-file", help="The file containing the password of the new user." ) parser.add_argument( "email", metavar="", nargs="?", default=argparse.SUPPRESS, help="email address of new user", ) parser.add_argument( "full_name", metavar="", nargs="?", default=argparse.SUPPRESS, help="full name of new user", ) self.add_realm_args( parser, required=True, help="The name of the existing realm to which to add the user." ) def handle(self, *args: Any, **options: Any) -> None: if not options["tos"]: raise CommandError( """You must confirm that this user has accepted the Terms of Service by passing --this-user-has-accepted-the-tos.""" ) realm = self.get_realm(options) assert realm is not None # Should be ensured by parser try: email = options["email"] full_name = options["full_name"] try: validators.validate_email(email) except ValidationError: raise CommandError("Invalid email address.") except KeyError: if "email" in options or "full_name" in options: raise CommandError( """Either specify an email and full name as two parameters, or specify no parameters for interactive user creation.""" ) else: while True: email = input("Email: ") try: validators.validate_email(email) break except ValidationError: print("Invalid email address.", file=sys.stderr) full_name = input("Full name: ") try: if options["password_file"] is not None: with open(options["password_file"]) as f: pw = f.read().strip() elif options["password"] is not None: pw = options["password"] else: user_initial_password = initial_password(email) if user_initial_password is None: raise CommandError("Password is unusable.") pw = user_initial_password do_create_user( email, pw, realm, full_name, acting_user=None, ) except IntegrityError: raise CommandError("User already exists.")