Updates the superuser management command to better handle existing super users

This commit is contained in:
Trenton Holmes 2022-05-09 09:38:17 -07:00
parent a789649d97
commit 4fd075aafa
No known key found for this signature in database
GPG Key ID: 4815A6E23A56B8D1
2 changed files with 197 additions and 47 deletions

View File

@ -11,7 +11,14 @@ logger = logging.getLogger("paperless.management.superuser")
class Command(BaseCommand): class Command(BaseCommand):
help = """ help = """
Creates a Django superuser based on env variables. Creates a Django superuser:
User named: admin
Email: root@localhost
with password based on env variable.
No superuser will be created, when:
- The username is taken already exists
- A superuser already exists
- PAPERLESS_ADMIN_PASSWORD is not set
""".replace( """.replace(
" ", " ",
"", "",
@ -19,26 +26,41 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
username = os.getenv("PAPERLESS_ADMIN_USER") username = os.getenv("PAPERLESS_ADMIN_USER", "admin")
if not username:
return
mail = os.getenv("PAPERLESS_ADMIN_MAIL", "root@localhost") mail = os.getenv("PAPERLESS_ADMIN_MAIL", "root@localhost")
password = os.getenv("PAPERLESS_ADMIN_PASSWORD") password = os.getenv("PAPERLESS_ADMIN_PASSWORD")
# Check if user exists already, leave as is if it does # Check if there's already a user called admin
if User.objects.filter(username=username).exists(): if User.objects.filter(username=username).exists():
user: User = User.objects.get_by_natural_key(username)
user.set_password(password)
user.save()
self.stdout.write(f"Changed password of user {username}.")
elif password:
# Create superuser based on env variables
User.objects.create_superuser(username, mail, password)
self.stdout.write(f'Created superuser "{username}" with provided password.')
else:
self.stdout.write(f'Did not create superuser "{username}".')
self.stdout.write( self.stdout.write(
'Make sure you specified "PAPERLESS_ADMIN_PASSWORD" in your ' self.style.NOTICE(
'"docker-compose.env" file.', f"Did not create superuser, a user {username} already exists",
),
)
return
# Check if any superuseruser
# exists already, leave as is if it does
if User.objects.filter(is_superuser=True).count() > 0:
self.stdout.write(
self.style.NOTICE(
"Did not create superuser, the DB already contains superusers",
),
)
return
if password is None:
self.stdout.write(
self.style.ERROR(
"Please check if PAPERLESS_ADMIN_PASSWORD has been"
" set in the environment",
),
)
else:
# Create superuser with password based on env variable
User.objects.create_superuser(username, mail, password)
self.stdout.write(
self.style.SUCCESS(
f'Created superuser "{username}" with provided password.',
),
) )

View File

@ -1,5 +1,6 @@
import os import os
import shutil import shutil
from io import StringIO
from unittest import mock from unittest import mock
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -15,53 +16,180 @@ from documents.tests.utils import DirectoriesMixin
class TestManageSuperUser(DirectoriesMixin, TestCase): class TestManageSuperUser(DirectoriesMixin, TestCase):
def reset_environment(self): def reset_environment(self):
if "PAPERLESS_ADMIN_USER" in os.environ:
del os.environ["PAPERLESS_ADMIN_USER"]
if "PAPERLESS_ADMIN_PASSWORD" in os.environ: if "PAPERLESS_ADMIN_PASSWORD" in os.environ:
del os.environ["PAPERLESS_ADMIN_PASSWORD"] del os.environ["PAPERLESS_ADMIN_PASSWORD"]
if "PAPERLESS_ADMIN_USER" in os.environ:
del os.environ["PAPERLESS_ADMIN_USER"]
if "PAPERLESS_ADMIN_MAIL" in os.environ:
del os.environ["PAPERLESS_ADMIN_MAIL"]
def setUp(self) -> None: def call_command(self, environ, *args, **kwargs):
super().setUp() out = StringIO()
self.reset_environment() with mock.patch.dict(os.environ, environ):
call_command(
def tearDown(self) -> None: "manage_superuser",
super().tearDown() "--no-color",
self.reset_environment() stdout=out,
stderr=StringIO(),
**kwargs,
)
return out.getvalue()
def test_no_user(self): def test_no_user(self):
call_command("manage_superuser") """
GIVEN:
- Environment does not contain admin user info
THEN:
- No admin user is created
"""
# just the consumer user. out = self.call_command(environ={})
# just the consumer user which is created
# during migration
self.assertEqual(User.objects.count(), 1) self.assertEqual(User.objects.count(), 1)
self.assertTrue(User.objects.filter(username="consumer").exists()) self.assertTrue(User.objects.filter(username="consumer").exists())
self.assertEqual(User.objects.filter(is_superuser=True).count(), 0)
self.assertEqual(
out,
"Please check if PAPERLESS_ADMIN_PASSWORD has been set in the environment\n",
)
def test_create(self): def test_create(self):
os.environ["PAPERLESS_ADMIN_USER"] = "new_user" """
os.environ["PAPERLESS_ADMIN_PASSWORD"] = "123456" GIVEN:
- Environment does contain admin user password
THEN:
- admin user is created
"""
call_command("manage_superuser") out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
user: User = User.objects.get_by_natural_key("new_user") # count is 2 as there's the consumer
self.assertTrue(user.check_password("123456")) # user already created during migration
user: User = User.objects.get_by_natural_key("admin")
self.assertEqual(User.objects.count(), 2)
self.assertTrue(user.is_superuser)
self.assertEqual(user.email, "root@localhost")
self.assertEqual(out, 'Created superuser "admin" with provided password.\n')
def test_update(self): def test_some_superuser_exists(self):
os.environ["PAPERLESS_ADMIN_USER"] = "new_user" """
os.environ["PAPERLESS_ADMIN_PASSWORD"] = "123456" GIVEN:
- A super user already exists
- Environment does contain admin user password
THEN:
- admin user is NOT created
"""
User.objects.create_superuser("someuser", "root@localhost", "password")
call_command("manage_superuser") out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
os.environ["PAPERLESS_ADMIN_USER"] = "new_user" self.assertEqual(User.objects.count(), 2)
os.environ["PAPERLESS_ADMIN_PASSWORD"] = "more_secure_pwd_7645" with self.assertRaises(User.DoesNotExist):
User.objects.get_by_natural_key("admin")
self.assertEqual(
out,
"Did not create superuser, the DB already contains superusers\n",
)
call_command("manage_superuser") def test_admin_superuser_exists(self):
"""
GIVEN:
- A super user already exists
- The existing superuser's username is admin
- Environment does contain admin user password
THEN:
- Password remains unchanged
"""
User.objects.create_superuser("admin", "root@localhost", "password")
user: User = User.objects.get_by_natural_key("new_user") out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
self.assertTrue(user.check_password("more_secure_pwd_7645"))
self.assertEqual(User.objects.count(), 2)
user: User = User.objects.get_by_natural_key("admin")
self.assertTrue(user.check_password("password"))
self.assertEqual(out, "Did not create superuser, a user admin already exists\n")
def test_admin_user_exists(self):
"""
GIVEN:
- A user already exists with the username admin
- Environment does contain admin user password
THEN:
- Password remains unchanged
- User is not upgraded to superuser
"""
User.objects.create_user("admin", "root@localhost", "password")
out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
self.assertEqual(User.objects.count(), 2)
user: User = User.objects.get_by_natural_key("admin")
self.assertTrue(user.check_password("password"))
self.assertFalse(user.is_superuser)
self.assertEqual(out, "Did not create superuser, a user admin already exists\n")
def test_no_password(self): def test_no_password(self):
os.environ["PAPERLESS_ADMIN_USER"] = "new_user" """
GIVEN:
call_command("manage_superuser") - No environment data is set
THEN:
- No user is created
"""
out = self.call_command(environ={})
with self.assertRaises(User.DoesNotExist): with self.assertRaises(User.DoesNotExist):
User.objects.get_by_natural_key("new_user") User.objects.get_by_natural_key("admin")
self.assertEqual(
out,
"Please check if PAPERLESS_ADMIN_PASSWORD has been set in the environment\n",
)
def test_user_email(self):
"""
GIVEN:
- Environment does contain admin user password
- Environment contains user email
THEN:
- admin user is created
"""
out = self.call_command(
environ={
"PAPERLESS_ADMIN_PASSWORD": "123456",
"PAPERLESS_ADMIN_MAIL": "hello@world.com",
},
)
user: User = User.objects.get_by_natural_key("admin")
self.assertEqual(User.objects.count(), 2)
self.assertTrue(user.is_superuser)
self.assertEqual(user.email, "hello@world.com")
self.assertEqual(user.username, "admin")
self.assertEqual(out, 'Created superuser "admin" with provided password.\n')
def test_user_username(self):
"""
GIVEN:
- Environment does contain admin user password
- Environment contains user username
THEN:
- admin user is created
"""
out = self.call_command(
environ={
"PAPERLESS_ADMIN_PASSWORD": "123456",
"PAPERLESS_ADMIN_MAIL": "hello@world.com",
"PAPERLESS_ADMIN_USER": "super",
},
)
user: User = User.objects.get_by_natural_key("super")
self.assertEqual(User.objects.count(), 2)
self.assertTrue(user.is_superuser)
self.assertEqual(user.email, "hello@world.com")
self.assertEqual(user.username, "super")
self.assertEqual(out, 'Created superuser "super" with provided password.\n')