# Buggy code
def createuser(email, password, superuser, no_password, no_input, force_update):
    "Create a new user."
    if not no_input:
        if not email:
            email = _get_email()

        if not (password or no_password):
            password = _get_password()

        if superuser is None:
            superuser = _get_superuser()

    if superuser is None:
        superuser = False

    if not email:
        raise click.ClickException("Invalid or missing email address.")

    # TODO(mattrobenolt): Accept password over stdin?
    if not no_password and not password:
        raise click.ClickException("No password set and --no-password not passed.")

    from sentry import roles
    from sentry.models import User
    from django.conf import settings

    user = User(
        email=email,
        username=email,
        is_superuser=superuser,
        is_staff=superuser,
        is_active=True,
    )

    if password:
        user.set_password(password)

    if User.objects.filter(username=email).exists():
        if force_update:
            user.save(force_update=force_update)
            click.echo(f"User updated: {email}")
        else:
            click.echo(f"User: {email} exists, use --force-update to force")
            sys.exit(3)
    else:
        user.save()
        click.echo(f"User created: {email}")

        # TODO(dcramer): kill this when we improve flows
        if settings.SENTRY_SINGLE_ORGANIZATION:
            from sentry.models import (
                Organization,
                OrganizationMember,
                OrganizationMemberTeam,
                Team,
            )

            org = Organization.get_default()
            if superuser:
                role = roles.get_top_dog().id
            else:
                role = org.default_role
            member = OrganizationMember.objects.create(
                organization=org, user=user, role=role
            )

            # if we've only got a single team let's go ahead and give
            # access to that team as its likely the desired outcome
            teams = list(Team.objects.filter(organization=org)[0:2])
            if len(teams) == 1:
                OrganizationMemberTeam.objects.create(
                    team=teams[0], organizationmember=member
                )
            click.echo(f"Added to organization: {org.slug}")


# Traceback (ValueError)
$ sudo docker-compose run --rm web sentry --version
sentry, version 10.1.0.dev0 (0bf9ffa08ff2)
$ sudo docker-compose run --rm web sentry createuser --email testuser@test.com --password pass1 --no-superuser --no-input --force-update
21:32:17 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
21:32:21 [INFO] sentry.plugins.github: apps-not-configured
User created: testuser@test.com
Added to organization: sentry
$ sudo docker-compose run --rm web sentry createuser --email testuser@test.com --password pass2 --no-superuser --no-input --force-update
21:33:46 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
21:33:49 [INFO] sentry.plugins.github: apps-not-configured
Traceback (most recent call last):
File "/usr/local/bin/sentry", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/sentry/runner/__init__.py", line 166, in main
cli(prog_name=get_prog(), obj={}, max_content_width=100)
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/sentry/runner/decorators.py", line 30, in inner
return ctx.invoke(f, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/sentry/runner/commands/createuser.py", line 83, in createuser
user.save(force_update=force_update)
File "/usr/local/lib/python2.7/site-packages/sentry/models/user.py", line 141, in save
return super(User, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 80, in save
super(AbstractBaseUser, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 808, in save
force_update=force_update, update_fields=update_fields)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 838, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 896, in _save_table
raise ValueError("Cannot force an update in save() with no primary key.")
ValueError: Cannot force an update in save() with no primary key.

# Fixed code
def createuser(email, password, superuser, no_password, no_input, force_update):
    "Create a new user."
    if not no_input:
        if not email:
            email = _get_email()

        if not (password or no_password):
            password = _get_password()

        if superuser is None:
            superuser = _get_superuser()

    if superuser is None:
        superuser = False

    if not email:
        raise click.ClickException("Invalid or missing email address.")

    # TODO(mattrobenolt): Accept password over stdin?
    if not no_password and not password:
        raise click.ClickException("No password set and --no-password not passed.")

    from sentry import roles
    from sentry.models import User
    from django.conf import settings

    fields = dict(
        email=email,
        username=email,
        is_superuser=superuser,
        is_staff=superuser,
        is_active=True,
    )

    verb = None
    try:
        user = User.objects.get(username=email)
    except User.DoesNotExist:
        user = None

    if user is not None:
        if force_update:
            user.update(**fields)
            verb = "updated"
        else:
            click.echo(f"User: {email} exists, use --force-update to force")
            sys.exit(3)
    else:
        user = User.objects.create(**fields)
        verb = "created"

        # TODO(dcramer): kill this when we improve flows
        if settings.SENTRY_SINGLE_ORGANIZATION:
            from sentry.models import (
                Organization,
                OrganizationMember,
                OrganizationMemberTeam,
                Team,
            )

            org = Organization.get_default()
            if superuser:
                role = roles.get_top_dog().id
            else:
                role = org.default_role
            member = OrganizationMember.objects.create(
                organization=org, user=user, role=role
            )

            # if we've only got a single team let's go ahead and give
            # access to that team as its likely the desired outcome
            teams = list(Team.objects.filter(organization=org)[0:2])
            if len(teams) == 1:
                OrganizationMemberTeam.objects.create(
                    team=teams[0], organizationmember=member
                )
            click.echo(f"Added to organization: {org.slug}")

    if password:
        user.set_password(password)
        user.save()

    click.echo(f"User {verb}: {email}")