prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  User-creation should not fail, when the account already exists
  I'm creating an Ansible role for installing sentry on our network. The software is installed via `pip` -- version 8.22.0, which seems to be the latest as of today. Not using Docker -- just a dedicated VM.
  
  One of the tasks is to create a Sentry-admin:
  ```
  sentry createuser --superuser --no-input --password=FOO --email=sentry@example.com
  ```
  Unfortunately, the above command only works _the first time_. Trying to run it again fails:
  ```
  django.db.utils.IntegrityError: IntegrityError('duplicate key value violates unique constraint \"auth_user_username_key\"
  DETAIL:  Key (username)=(sentry@example.com) already exists
  ```
  I understand, why the same account can not be created again. But it should not be an _error_ -- simply update the existing record if necessary. Or, if it must be an error, there should be a specific exit-code for this case, which would allow systems like Ansible to move on. Currently, `sentry` exits with the same code 1 for all errors...
  
  At the very least, there needs to be a way to check, whether the account exists already... Ansible would then be able to perform the query before attempting to add the user.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/sentry/runner/commands/createuser.py`
  Content:
  ```
  1 from __future__ import absolute_import, print_function
  2 
  3 import click
  4 from sentry.runner.decorators import configuration
  5 
  6 
  7 def _get_field(field_name):
  8     from sentry.models import User
  9 
  10     return User._meta.get_field(field_name)
  11 
  12 
  13 def _get_email():
  14     from django.core.exceptions import ValidationError
  15 
  16     rv = click.prompt("Email")
  17     field = _get_field("email")
  18     try:
  19         return field.clean(rv, None)
  20     except ValidationError as e:
  21         raise click.ClickException("; ".join(e.messages))
  22 
  23 
  24 def _get_password():
  25     from django.core.exceptions import ValidationError
  26 
  27     rv = click.prompt("Password", hide_input=True, confirmation_prompt=True)
  28     field = _get_field("password")
  29     try:
  30         return field.clean(rv, None)
  31     except ValidationError as e:
  32         raise click.ClickException("; ".join(e.messages))
  33 
  34 
  35 def _get_superuser():
  36     return click.confirm("Should this user be a superuser?", default=False)
  37 
  38 
  39 @click.command()
  40 @click.option("--email")
  41 @click.option("--password")
  42 @click.option("--superuser/--no-superuser", default=None, is_flag=True)
  43 @click.option("--no-password", default=False, is_flag=True)
  44 @click.option("--no-input", default=False, is_flag=True)
  45 @configuration
  46 def createuser(email, password, superuser, no_password, no_input):
  47     "Create a new user."
  48     if not no_input:
  49         if not email:
  50             email = _get_email()
  51 
  52         if not (password or no_password):
  53             password = _get_password()
  54 
  55         if superuser is None:
  56             superuser = _get_superuser()
  57 
  58     if superuser is None:
  59         superuser = False
  60 
  61     if not email:
  62         raise click.ClickException("Invalid or missing email address.")
  63 
  64     # TODO(mattrobenolt): Accept password over stdin?
  65     if not no_password and not password:
  66         raise click.ClickException("No password set and --no-password not passed.")
  67 
  68     from sentry import roles
  69     from sentry.models import User
  70     from django.conf import settings
  71 
  72     user = User(
  73         email=email, username=email, is_superuser=superuser, is_staff=superuser, is_active=True
  74     )
  75 
  76     if password:
  77         user.set_password(password)
  78 
  79     user.save()
  80 
  81     click.echo("User created: %s" % (email,))
  82 
  83     # TODO(dcramer): kill this when we improve flows
  84     if settings.SENTRY_SINGLE_ORGANIZATION:
  85         from sentry.models import Organization, OrganizationMember, OrganizationMemberTeam, Team
  86 
  87         org = Organization.get_default()
  88         if superuser:
  89             role = roles.get_top_dog().id
  90         else:
  91             role = org.default_role
  92         member = OrganizationMember.objects.create(organization=org, user=user, role=role)
  93 
  94         # if we've only got a single team let's go ahead and give
  95         # access to that team as its likely the desired outcome
  96         teams = list(Team.objects.filter(organization=org)[0:2])
  97         if len(teams) == 1:
  98             OrganizationMemberTeam.objects.create(team=teams[0], organizationmember=member)
  99         click.echo("Added to organization: %s" % (org.slug,))
  100
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/sentry/runner/commands/createuser.py b/src/sentry/runner/commands/createuser.py
  --- a/src/sentry/runner/commands/createuser.py
  +++ b/src/sentry/runner/commands/createuser.py
  @@ -1,6 +1,7 @@
   from __future__ import absolute_import, print_function
   
   import click
  +import sys
   from sentry.runner.decorators import configuration
   
   
  @@ -42,8 +43,9 @@
   @click.option("--superuser/--no-superuser", default=None, is_flag=True)
   @click.option("--no-password", default=False, is_flag=True)
   @click.option("--no-input", default=False, is_flag=True)
  +@click.option("--force-update", default=False, is_flag=True)
   @configuration
  -def createuser(email, password, superuser, no_password, no_input):
  +def createuser(email, password, superuser, no_password, no_input, force_update):
       "Create a new user."
       if not no_input:
           if not email:
  @@ -76,24 +78,31 @@
       if password:
           user.set_password(password)
   
  -    user.save()
  -
  -    click.echo("User created: %s" % (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
  +    if User.objects.filter(username=email).exists():
  +        if force_update:
  +            user.save(force_update=force_update)
  +            click.echo("User updated: %s" % (email,))
           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("Added to organization: %s" % (org.slug,))
  +            click.echo("User: %s exists, use --force-update to force" % (email,))
  +            sys.exit(3)
  +    else:
  +        user.save()
  +        click.echo("User created: %s" % (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("Added to organization: %s" % (org.slug,))
  
verification_info: {"golden_diff": "diff --git a/src/sentry/runner/commands/createuser.py b/src/sentry/runner/commands/createuser.py\n--- a/src/sentry/runner/commands/createuser.py\n+++ b/src/sentry/runner/commands/createuser.py\n@@ -1,6 +1,7 @@\n from __future__ import absolute_import, print_function\n \n import click\n+import sys\n from sentry.runner.decorators import configuration\n \n \n@@ -42,8 +43,9 @@\n @click.option(\"--superuser/--no-superuser\", default=None, is_flag=True)\n @click.option(\"--no-password\", default=False, is_flag=True)\n @click.option(\"--no-input\", default=False, is_flag=True)\n+@click.option(\"--force-update\", default=False, is_flag=True)\n @configuration\n-def createuser(email, password, superuser, no_password, no_input):\n+def createuser(email, password, superuser, no_password, no_input, force_update):\n     \"Create a new user.\"\n     if not no_input:\n         if not email:\n@@ -76,24 +78,31 @@\n     if password:\n         user.set_password(password)\n \n-    user.save()\n-\n-    click.echo(\"User created: %s\" % (email,))\n-\n-    # TODO(dcramer): kill this when we improve flows\n-    if settings.SENTRY_SINGLE_ORGANIZATION:\n-        from sentry.models import Organization, OrganizationMember, OrganizationMemberTeam, Team\n-\n-        org = Organization.get_default()\n-        if superuser:\n-            role = roles.get_top_dog().id\n+    if User.objects.filter(username=email).exists():\n+        if force_update:\n+            user.save(force_update=force_update)\n+            click.echo(\"User updated: %s\" % (email,))\n         else:\n-            role = org.default_role\n-        member = OrganizationMember.objects.create(organization=org, user=user, role=role)\n-\n-        # if we've only got a single team let's go ahead and give\n-        # access to that team as its likely the desired outcome\n-        teams = list(Team.objects.filter(organization=org)[0:2])\n-        if len(teams) == 1:\n-            OrganizationMemberTeam.objects.create(team=teams[0], organizationmember=member)\n-        click.echo(\"Added to organization: %s\" % (org.slug,))\n+            click.echo(\"User: %s exists, use --force-update to force\" % (email,))\n+            sys.exit(3)\n+    else:\n+        user.save()\n+        click.echo(\"User created: %s\" % (email,))\n+\n+        # TODO(dcramer): kill this when we improve flows\n+        if settings.SENTRY_SINGLE_ORGANIZATION:\n+            from sentry.models import Organization, OrganizationMember, OrganizationMemberTeam, Team\n+\n+            org = Organization.get_default()\n+            if superuser:\n+                role = roles.get_top_dog().id\n+            else:\n+                role = org.default_role\n+            member = OrganizationMember.objects.create(organization=org, user=user, role=role)\n+\n+            # if we've only got a single team let's go ahead and give\n+            # access to that team as its likely the desired outcome\n+            teams = list(Team.objects.filter(organization=org)[0:2])\n+            if len(teams) == 1:\n+                OrganizationMemberTeam.objects.create(team=teams[0], organizationmember=member)\n+            click.echo(\"Added to organization: %s\" % (org.slug,))\n", "issue": "User-creation should not fail, when the account already exists\nI'm creating an Ansible role for installing sentry on our network. The software is installed via `pip` -- version 8.22.0, which seems to be the latest as of today. Not using Docker -- just a dedicated VM.\r\n\r\nOne of the tasks is to create a Sentry-admin:\r\n```\r\nsentry createuser --superuser --no-input --password=FOO --email=sentry@example.com\r\n```\r\nUnfortunately, the above command only works _the first time_. Trying to run it again fails:\r\n```\r\ndjango.db.utils.IntegrityError: IntegrityError('duplicate key value violates unique constraint \\\"auth_user_username_key\\\"\r\nDETAIL:  Key (username)=(sentry@example.com) already exists\r\n```\r\nI understand, why the same account can not be created again. But it should not be an _error_ -- simply update the existing record if necessary. Or, if it must be an error, there should be a specific exit-code for this case, which would allow systems like Ansible to move on. Currently, `sentry` exits with the same code 1 for all errors...\r\n\r\nAt the very least, there needs to be a way to check, whether the account exists already... Ansible would then be able to perform the query before attempting to add the user.\r\n\n", "before_files": [{"content": "from __future__ import absolute_import, print_function\n\nimport click\nfrom sentry.runner.decorators import configuration\n\n\ndef _get_field(field_name):\n    from sentry.models import User\n\n    return User._meta.get_field(field_name)\n\n\ndef _get_email():\n    from django.core.exceptions import ValidationError\n\n    rv = click.prompt(\"Email\")\n    field = _get_field(\"email\")\n    try:\n        return field.clean(rv, None)\n    except ValidationError as e:\n        raise click.ClickException(\"; \".join(e.messages))\n\n\ndef _get_password():\n    from django.core.exceptions import ValidationError\n\n    rv = click.prompt(\"Password\", hide_input=True, confirmation_prompt=True)\n    field = _get_field(\"password\")\n    try:\n        return field.clean(rv, None)\n    except ValidationError as e:\n        raise click.ClickException(\"; \".join(e.messages))\n\n\ndef _get_superuser():\n    return click.confirm(\"Should this user be a superuser?\", default=False)\n\n\n@click.command()\n@click.option(\"--email\")\n@click.option(\"--password\")\n@click.option(\"--superuser/--no-superuser\", default=None, is_flag=True)\n@click.option(\"--no-password\", default=False, is_flag=True)\n@click.option(\"--no-input\", default=False, is_flag=True)\n@configuration\ndef createuser(email, password, superuser, no_password, no_input):\n    \"Create a new user.\"\n    if not no_input:\n        if not email:\n            email = _get_email()\n\n        if not (password or no_password):\n            password = _get_password()\n\n        if superuser is None:\n            superuser = _get_superuser()\n\n    if superuser is None:\n        superuser = False\n\n    if not email:\n        raise click.ClickException(\"Invalid or missing email address.\")\n\n    # TODO(mattrobenolt): Accept password over stdin?\n    if not no_password and not password:\n        raise click.ClickException(\"No password set and --no-password not passed.\")\n\n    from sentry import roles\n    from sentry.models import User\n    from django.conf import settings\n\n    user = User(\n        email=email, username=email, is_superuser=superuser, is_staff=superuser, is_active=True\n    )\n\n    if password:\n        user.set_password(password)\n\n    user.save()\n\n    click.echo(\"User created: %s\" % (email,))\n\n    # TODO(dcramer): kill this when we improve flows\n    if settings.SENTRY_SINGLE_ORGANIZATION:\n        from sentry.models import Organization, OrganizationMember, OrganizationMemberTeam, Team\n\n        org = Organization.get_default()\n        if superuser:\n            role = roles.get_top_dog().id\n        else:\n            role = org.default_role\n        member = OrganizationMember.objects.create(organization=org, user=user, role=role)\n\n        # if we've only got a single team let's go ahead and give\n        # access to that team as its likely the desired outcome\n        teams = list(Team.objects.filter(organization=org)[0:2])\n        if len(teams) == 1:\n            OrganizationMemberTeam.objects.create(team=teams[0], organizationmember=member)\n        click.echo(\"Added to organization: %s\" % (org.slug,))\n", "path": "src/sentry/runner/commands/createuser.py"}], "after_files": [{"content": "from __future__ import absolute_import, print_function\n\nimport click\nimport sys\nfrom sentry.runner.decorators import configuration\n\n\ndef _get_field(field_name):\n    from sentry.models import User\n\n    return User._meta.get_field(field_name)\n\n\ndef _get_email():\n    from django.core.exceptions import ValidationError\n\n    rv = click.prompt(\"Email\")\n    field = _get_field(\"email\")\n    try:\n        return field.clean(rv, None)\n    except ValidationError as e:\n        raise click.ClickException(\"; \".join(e.messages))\n\n\ndef _get_password():\n    from django.core.exceptions import ValidationError\n\n    rv = click.prompt(\"Password\", hide_input=True, confirmation_prompt=True)\n    field = _get_field(\"password\")\n    try:\n        return field.clean(rv, None)\n    except ValidationError as e:\n        raise click.ClickException(\"; \".join(e.messages))\n\n\ndef _get_superuser():\n    return click.confirm(\"Should this user be a superuser?\", default=False)\n\n\n@click.command()\n@click.option(\"--email\")\n@click.option(\"--password\")\n@click.option(\"--superuser/--no-superuser\", default=None, is_flag=True)\n@click.option(\"--no-password\", default=False, is_flag=True)\n@click.option(\"--no-input\", default=False, is_flag=True)\n@click.option(\"--force-update\", default=False, is_flag=True)\n@configuration\ndef createuser(email, password, superuser, no_password, no_input, force_update):\n    \"Create a new user.\"\n    if not no_input:\n        if not email:\n            email = _get_email()\n\n        if not (password or no_password):\n            password = _get_password()\n\n        if superuser is None:\n            superuser = _get_superuser()\n\n    if superuser is None:\n        superuser = False\n\n    if not email:\n        raise click.ClickException(\"Invalid or missing email address.\")\n\n    # TODO(mattrobenolt): Accept password over stdin?\n    if not no_password and not password:\n        raise click.ClickException(\"No password set and --no-password not passed.\")\n\n    from sentry import roles\n    from sentry.models import User\n    from django.conf import settings\n\n    user = User(\n        email=email, username=email, is_superuser=superuser, is_staff=superuser, is_active=True\n    )\n\n    if password:\n        user.set_password(password)\n\n    if User.objects.filter(username=email).exists():\n        if force_update:\n            user.save(force_update=force_update)\n            click.echo(\"User updated: %s\" % (email,))\n        else:\n            click.echo(\"User: %s exists, use --force-update to force\" % (email,))\n            sys.exit(3)\n    else:\n        user.save()\n        click.echo(\"User created: %s\" % (email,))\n\n        # TODO(dcramer): kill this when we improve flows\n        if settings.SENTRY_SINGLE_ORGANIZATION:\n            from sentry.models import Organization, OrganizationMember, OrganizationMemberTeam, Team\n\n            org = Organization.get_default()\n            if superuser:\n                role = roles.get_top_dog().id\n            else:\n                role = org.default_role\n            member = OrganizationMember.objects.create(organization=org, user=user, role=role)\n\n            # if we've only got a single team let's go ahead and give\n            # access to that team as its likely the desired outcome\n            teams = list(Team.objects.filter(organization=org)[0:2])\n            if len(teams) == 1:\n                OrganizationMemberTeam.objects.create(team=teams[0], organizationmember=member)\n            click.echo(\"Added to organization: %s\" % (org.slug,))\n", "path": "src/sentry/runner/commands/createuser.py"}]}