-
Notifications
You must be signed in to change notification settings - Fork 927
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support bootstrapping a Django/Wagtail admin user as part of `make pr…
…eflight` (#14813) If using sqlite locally, when `make preflight` runs, it will replace your local DB. This changeset at least bootstraps a new admin user for you, even if any local CMS pages will have been lost
- Loading branch information
1 parent
ff5c501
commit caf5db8
Showing
3 changed files
with
126 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
|
||
import sys | ||
|
||
from django.contrib.auth.models import User | ||
from django.core.management.base import BaseCommand | ||
from django.db.transaction import atomic | ||
|
||
from bedrock.base.config_manager import config | ||
|
||
|
||
class Command(BaseCommand): | ||
help = """Creates a Django/Wagtail Admin User based on the Mozilla | ||
email address set as the WAGTAIL_ADMIN_EMAIL environment variable. | ||
Optionally also sets a non-SSO password for that new user based on | ||
WAGTAIL_ADMIN_PASSWORD""" | ||
|
||
@atomic | ||
def handle(self, *args, **kwargs): | ||
WAGTAIL_ADMIN_EMAIL = config("WAGTAIL_ADMIN_EMAIL", default="") | ||
WAGTAIL_ADMIN_PASSWORD = config("WAGTAIL_ADMIN_PASSWORD", default="") | ||
|
||
if not WAGTAIL_ADMIN_EMAIL: | ||
sys.stdout.write("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment.") | ||
return | ||
if not WAGTAIL_ADMIN_EMAIL.endswith("@mozilla.com"): | ||
sys.stdout.write("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL is not a @mozilla.com email address.") | ||
return | ||
|
||
user, created = User.objects.get_or_create(email=WAGTAIL_ADMIN_EMAIL) | ||
if not created: | ||
sys.stdout.write(f"Admin user {WAGTAIL_ADMIN_EMAIL} already exists") | ||
else: | ||
user.username = WAGTAIL_ADMIN_EMAIL | ||
user.is_staff = True | ||
user.is_superuser = True | ||
if not WAGTAIL_ADMIN_PASSWORD: | ||
user.set_unusable_password() # They won't need one to use SSO | ||
sys.stdout.write(f"Created Admin user {WAGTAIL_ADMIN_EMAIL} for local SSO use") | ||
else: | ||
user.set_password(WAGTAIL_ADMIN_PASSWORD) | ||
sys.stdout.write(f"Created Admin user {WAGTAIL_ADMIN_EMAIL} with password '{WAGTAIL_ADMIN_PASSWORD}'") | ||
user.save() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
from io import StringIO | ||
from unittest.mock import patch | ||
from unittest.mock import call, patch | ||
|
||
from django.conf import settings | ||
from django.contrib.auth.models import User | ||
|
@@ -87,3 +87,81 @@ def test_scrub(self): | |
self.assertEqual(Revision.objects.count(), 0) | ||
self.assertEqual(TranslationSource.objects.count(), 0) | ||
self.assertEqual(SimpleRichTextPage.objects.count(), 3) # pages are unaffected | ||
|
||
|
||
@patch("bedrock.cms.management.commands.bootstrap_local_admin.sys.stdout.write") | ||
class BootstrapLocalAdminTests(TransactionTestCase): | ||
def _run_test(self, mock_write, expected_output): | ||
out = StringIO() | ||
call_command("bootstrap_local_admin", stdout=out) | ||
output = mock_write.call_args_list | ||
self.assertEqual(output, expected_output) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "", "WAGTAIL_ADMIN_PASSWORD": ""}) | ||
def test_no_env_vars_available(self, mock_write): | ||
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment."), | ||
], | ||
) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "[email protected]", "WAGTAIL_ADMIN_PASSWORD": ""}) | ||
def test_email_available(self, mock_write): | ||
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Created Admin user [email protected] for local SSO use"), | ||
], | ||
) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "[email protected]", "WAGTAIL_ADMIN_PASSWORD": ""}) | ||
def test_email_available_but_not_moco(self, mock_write): | ||
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL is not a @mozilla.com email address."), | ||
], | ||
) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "[email protected]", "WAGTAIL_ADMIN_PASSWORD": "secret"}) | ||
def test_email_and_password_available(self, mock_write): | ||
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Created Admin user [email protected] with password 'secret'"), | ||
], | ||
) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "", "WAGTAIL_ADMIN_PASSWORD": ""}) | ||
def test_only_password_available(self, mock_write): | ||
self._run_test( | ||
mock_write=mock_write, | ||
expected_output=[ | ||
call("Not bootstrapping an Admin user: WAGTAIL_ADMIN_EMAIL not defined in environment."), | ||
], | ||
) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "[email protected]", "WAGTAIL_ADMIN_PASSWORD": ""}) | ||
def test_existing_user_exists_email_only(self, mock_write): | ||
out = StringIO() | ||
call_command("bootstrap_local_admin", stdout=out) | ||
call_command("bootstrap_local_admin", stdout=out) | ||
output = mock_write.call_args_list | ||
expected_output = [ | ||
call("Created Admin user [email protected] for local SSO use"), | ||
call("Admin user [email protected] already exists"), | ||
] | ||
self.assertEqual(output, expected_output) | ||
|
||
@patch.dict("os.environ", {"WAGTAIL_ADMIN_EMAIL": "[email protected]", "WAGTAIL_ADMIN_PASSWORD": "secret"}) | ||
def test_existing_user_exists_email_and_password(self, mock_write): | ||
out = StringIO() | ||
call_command("bootstrap_local_admin", stdout=out) | ||
call_command("bootstrap_local_admin", stdout=out) | ||
output = mock_write.call_args_list | ||
expected_output = [ | ||
call("Created Admin user [email protected] with password 'secret'"), | ||
call("Admin user [email protected] already exists"), | ||
] | ||
self.assertEqual(output, expected_output) |