mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
Comments, docstrings and live test names cited item IDs of a roadmap that is not part of the repository. They now say what is meant, or nothing where the sentence stands without them. Test assertions and behavior are unchanged.
92 lines
4.3 KiB
Python
92 lines
4.3 KiB
Python
"""The generated admin password must not be printed to the log."""
|
|
import io
|
|
import os
|
|
import stat
|
|
import tempfile
|
|
from contextlib import redirect_stdout
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from django.apps import apps
|
|
from django.contrib.auth import authenticate, get_user_model
|
|
from django.test import TestCase, override_settings
|
|
|
|
from accounts.apps import create_admin
|
|
from accounts.models import UserAttributes
|
|
|
|
|
|
class GeneratedAdminPasswordTestCase(TestCase):
|
|
def _run_create_admin(self, base_dir, plan=None):
|
|
get_user_model().objects.all().delete()
|
|
if plan is None:
|
|
migration = MagicMock(app_label="accounts")
|
|
migration.name = "0001_initial"
|
|
plan = [(migration, False)]
|
|
out = io.StringIO()
|
|
env = {k: v for k, v in os.environ.items() if k not in ("ADMIN_PASSWORD", "ADMIN_USERNAME")}
|
|
with override_settings(BASE_DIR=Path(base_dir)), patch("sys.argv", ["manage.py", "migrate"]), patch.dict(
|
|
os.environ, env, clear=True
|
|
), redirect_stdout(out):
|
|
create_admin(sender=None, plan=plan, apps=apps)
|
|
return out.getvalue()
|
|
|
|
def test_password_is_written_to_a_private_file_not_printed(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
(Path(tmp) / "data").mkdir()
|
|
output = self._run_create_admin(tmp)
|
|
password_file = Path(tmp) / "data" / "admin_password"
|
|
|
|
self.assertTrue(password_file.exists())
|
|
password = password_file.read_text().strip()
|
|
self.assertEqual(stat.S_IMODE(password_file.stat().st_mode), 0o600)
|
|
self.assertNotIn(password, output)
|
|
self.assertIn(str(password_file), output)
|
|
self.assertIsNotNone(authenticate(username="admin", password=password))
|
|
self.assertTrue(UserAttributes.objects.get(user__username="admin").must_change_password)
|
|
|
|
def test_does_not_follow_a_planted_symlink(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
(Path(tmp) / "data").mkdir()
|
|
victim = Path(tmp) / "victim"
|
|
victim.write_text("original\n")
|
|
(Path(tmp) / "data" / "admin_password").symlink_to(victim)
|
|
|
|
self._run_create_admin(tmp)
|
|
|
|
password_file = Path(tmp) / "data" / "admin_password"
|
|
self.assertEqual(victim.read_text(), "original\n")
|
|
self.assertFalse(password_file.is_symlink())
|
|
self.assertEqual(stat.S_IMODE(password_file.stat().st_mode), 0o600)
|
|
|
|
def test_storage_failure_does_not_print_password_or_create_an_admin(self):
|
|
password = "review-dummy-generated-password"
|
|
output = io.StringIO()
|
|
with tempfile.TemporaryDirectory() as tmp, patch(
|
|
"secrets.token_urlsafe", return_value=password
|
|
), patch("accounts.apps.os.open", side_effect=PermissionError("read-only")), redirect_stdout(output):
|
|
with self.assertRaisesRegex(RuntimeError, "Cannot securely store"):
|
|
self._run_create_admin(tmp)
|
|
self.assertNotIn(password, output.getvalue())
|
|
self.assertFalse(get_user_model().objects.exists())
|
|
|
|
def test_rerunning_migrate_after_a_storage_failure_creates_the_admin(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
with patch("accounts.apps.os.open", side_effect=PermissionError("read-only")), redirect_stdout(io.StringIO()):
|
|
with self.assertRaises(RuntimeError):
|
|
self._run_create_admin(tmp)
|
|
# The second migrate has nothing left to apply: an empty plan.
|
|
(Path(tmp) / "data").mkdir(exist_ok=True)
|
|
self._run_create_admin(tmp, plan=[])
|
|
self.assertTrue(get_user_model().objects.filter(username="admin").exists())
|
|
|
|
def test_flush_does_not_create_an_admin(self):
|
|
get_user_model().objects.all().delete()
|
|
create_admin(sender=None, plan=None, apps=apps)
|
|
self.assertFalse(get_user_model().objects.exists())
|
|
|
|
def test_migrating_another_app_before_auth_creates_nothing(self):
|
|
get_user_model().objects.all().delete()
|
|
state_without_auth = MagicMock()
|
|
state_without_auth.get_model.side_effect = LookupError
|
|
create_admin(sender=None, plan=[], apps=state_without_auth)
|
|
self.assertFalse(get_user_model().objects.exists())
|