Skip to content

Commit

Permalink
Adds a promote_user command to make it easier to promote/demote a u…
Browse files Browse the repository at this point in the history
…ser. (#167)
  • Loading branch information
jkachel authored Nov 12, 2024
1 parent 2b2627f commit 5b92afd
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 0 deletions.
Empty file.
Empty file.
85 changes: 85 additions & 0 deletions unified_ecommerce/management/commands/promote_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""Promote/demote a user."""

from django.contrib.auth import get_user_model
from django.core.management import BaseCommand, CommandError


class Command(BaseCommand):
"""Promote/demote a user."""

help = "Promote/demote a user."

def add_arguments(self, parser):
"""Add arguments to the command."""

parser.add_argument(
"email",
type=str,
help="The email of the user to promote/demote.",
)

parser.add_argument(
"--promote",
action="store_true",
help="Promote the user to staff.",
)

parser.add_argument(
"--demote",
action="store_true",
help="Demote the user from staff.",
)

parser.add_argument(
"--superuser",
action="store_true",
help="Promote the user to superuser.",
)

def handle(self, **options) -> None:
"""Handle the command."""

email = options["email"]
promote = options["promote"]
demote = options["demote"]
superuser = options["superuser"]
verb = ""

User = get_user_model()

try:
user = User.objects.get(email=email)
except User.DoesNotExist as exc:
errmsg = f"User with email {email} does not exist."
raise CommandError(errmsg) from exc

if promote and demote:
errmsg = "You cannot provide both --promote and --demote."
raise CommandError(errmsg)

if promote:
verb = "promoted"
user.is_staff = True

if superuser:
verb = f"{verb} to superuser"
user.is_superuser = True

user.save()
elif demote:
verb = "demoted"
# Demoting a superuser just makes them staff.
if superuser:
verb = f"{verb} from superuser to staff"
user.is_staff = True
user.is_superuser = False
else:
user.is_staff = False
user.is_superuser = False

user.save()
else:
errmsg = "You must provide either --promote or --demote."
raise CommandError(errmsg)

self.stdout.write(self.style.SUCCESS(f"Successfully {verb} user {user.email}."))
Empty file.
121 changes: 121 additions & 0 deletions unified_ecommerce/management/tests/promote_user_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""Tests for the promote_user command"""

from io import StringIO

import faker
import pytest
from django.core.management import CommandError, call_command

pytestmark = pytest.mark.django_db
FAKE = faker.Faker()


def test_promote_user_bad_args(user):
"""Test that the command raises an error with bad arguments."""
out = StringIO()

with pytest.raises(CommandError) as exc:
call_command(
"promote_user",
"--promote",
"--demote",
user.email,
stdout=out,
)

assert "You cannot provide both --promote and --demote." in str(exc.value)

with pytest.raises(CommandError) as exc:
call_command(
"promote_user",
"--promote",
FAKE.email(),
stdout=out,
)

assert "User with email" in str(exc.value)

with pytest.raises(CommandError) as exc:
call_command(
"promote_user",
"--superuser",
user.email,
stdout=out,
)

assert "You must provide either --promote or --demote" in str(exc.value)


@pytest.mark.parametrize("to_superuser", [True, False])
def test_promote_user(user, to_superuser):
"""Test that promote_user promotes the user correctly."""
out = StringIO()

if to_superuser:
call_command(
"promote_user",
"--promote",
"--superuser",
user.email,
stdout=out,
)
else:
call_command(
"promote_user",
"--promote",
user.email,
stdout=out,
)

user.refresh_from_db()

assert "promoted" in out.getvalue()

if to_superuser:
assert "to superuser" in out.getvalue()
else:
assert "to superuser" not in out.getvalue()

assert user.is_superuser == to_superuser
assert user.is_staff


@pytest.mark.parametrize("from_superuser", [True, False])
def test_demote_user(user, from_superuser):
"""Test that promote_user demotes the user correctly."""
out = StringIO()

if from_superuser:
user.is_superuser = True
user.is_staff = True
user.save()

call_command(
"promote_user",
"--demote",
"--superuser",
user.email,
stdout=out,
)
else:
user.is_staff = True
user.save()

call_command(
"promote_user",
"--demote",
user.email,
stdout=out,
)

user.refresh_from_db()

assert "demoted" in out.getvalue()

if from_superuser:
assert "to staff" in out.getvalue()
assert not user.is_superuser
assert user.is_staff
else:
assert not user.is_superuser
assert not user.is_staff

0 comments on commit 5b92afd

Please sign in to comment.