]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Updates the superuser management command to better handle existing super users
authorTrenton Holmes <holmes.trenton@gmail.com>
Mon, 9 May 2022 16:38:17 +0000 (09:38 -0700)
committerTrenton Holmes <holmes.trenton@gmail.com>
Mon, 9 May 2022 16:38:17 +0000 (09:38 -0700)
src/documents/management/commands/manage_superuser.py
src/documents/tests/test_management_superuser.py

index e892f7d2233380efd6c3bc625ee92ccc5822daaa..2f506b54a1992788d8229db287581dc7a224eae9 100644 (file)
@@ -11,7 +11,14 @@ logger = logging.getLogger("paperless.management.superuser")
 class Command(BaseCommand):
 
     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(
         "    ",
         "",
@@ -19,26 +26,41 @@ class Command(BaseCommand):
 
     def handle(self, *args, **options):
 
-        username = os.getenv("PAPERLESS_ADMIN_USER")
-        if not username:
-            return
-
+        username = os.getenv("PAPERLESS_ADMIN_USER", "admin")
         mail = os.getenv("PAPERLESS_ADMIN_MAIL", "root@localhost")
         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():
-            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.')
+            self.stdout.write(
+                self.style.NOTICE(
+                    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:
-            self.stdout.write(f'Did not create superuser "{username}".')
+            # Create superuser with password based on env variable
+            User.objects.create_superuser(username, mail, password)
             self.stdout.write(
-                'Make sure you specified "PAPERLESS_ADMIN_PASSWORD" in your '
-                '"docker-compose.env" file.',
+                self.style.SUCCESS(
+                    f'Created superuser "{username}" with provided password.',
+                ),
             )
index b4e91fd6615c8e6887c4fc5d276cb123c478775d..4a8bb7bb31b56bc8f2ec4254c5b45245decc557f 100644 (file)
@@ -1,5 +1,6 @@
 import os
 import shutil
+from io import StringIO
 from unittest import mock
 
 from django.contrib.auth.models import User
@@ -15,53 +16,180 @@ from documents.tests.utils import DirectoriesMixin
 
 class TestManageSuperUser(DirectoriesMixin, TestCase):
     def reset_environment(self):
-        if "PAPERLESS_ADMIN_USER" in os.environ:
-            del os.environ["PAPERLESS_ADMIN_USER"]
         if "PAPERLESS_ADMIN_PASSWORD" in os.environ:
             del os.environ["PAPERLESS_ADMIN_PASSWORD"]
-
-    def setUp(self) -> None:
-        super().setUp()
-        self.reset_environment()
-
-    def tearDown(self) -> None:
-        super().tearDown()
-        self.reset_environment()
+        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 call_command(self, environ, *args, **kwargs):
+        out = StringIO()
+        with mock.patch.dict(os.environ, environ):
+            call_command(
+                "manage_superuser",
+                "--no-color",
+                stdout=out,
+                stderr=StringIO(),
+                **kwargs,
+            )
+        return out.getvalue()
 
     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.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):
-        os.environ["PAPERLESS_ADMIN_USER"] = "new_user"
-        os.environ["PAPERLESS_ADMIN_PASSWORD"] = "123456"
-
-        call_command("manage_superuser")
-
-        user: User = User.objects.get_by_natural_key("new_user")
-        self.assertTrue(user.check_password("123456"))
-
-    def test_update(self):
-        os.environ["PAPERLESS_ADMIN_USER"] = "new_user"
-        os.environ["PAPERLESS_ADMIN_PASSWORD"] = "123456"
-
-        call_command("manage_superuser")
-
-        os.environ["PAPERLESS_ADMIN_USER"] = "new_user"
-        os.environ["PAPERLESS_ADMIN_PASSWORD"] = "more_secure_pwd_7645"
-
-        call_command("manage_superuser")
-
-        user: User = User.objects.get_by_natural_key("new_user")
-        self.assertTrue(user.check_password("more_secure_pwd_7645"))
+        """
+        GIVEN:
+            - Environment does contain admin user password
+        THEN:
+            - admin user is created
+        """
+
+        out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
+
+        # count is 2 as there's the consumer
+        # 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_some_superuser_exists(self):
+        """
+        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")
+
+        out = self.call_command(environ={"PAPERLESS_ADMIN_PASSWORD": "123456"})
+
+        self.assertEqual(User.objects.count(), 2)
+        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",
+        )
+
+    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")
+
+        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.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):
-        os.environ["PAPERLESS_ADMIN_USER"] = "new_user"
-
-        call_command("manage_superuser")
+        """
+        GIVEN:
+            - No environment data is set
+        THEN:
+            - No user is created
+        """
+        out = self.call_command(environ={})
 
         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')