fix: persist preview admin access
This commit is contained in:
@@ -118,6 +118,25 @@ python manage.py ensure_superuser
|
|||||||
python manage.py runserver
|
python manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Persistent local preview without Docker
|
||||||
|
|
||||||
|
The local preview uses `instance/preview.sqlite3`, which survives server restarts and is
|
||||||
|
ignored by Git. Put the preview admin credentials in `instance/preview_admin.env`
|
||||||
|
(also ignored by Git):
|
||||||
|
|
||||||
|
```text
|
||||||
|
DJANGO_SUPERUSER_USERNAME=admin
|
||||||
|
DJANGO_SUPERUSER_EMAIL=admin@localhost
|
||||||
|
DJANGO_SUPERUSER_PASSWORD=your-local-password
|
||||||
|
DJANGO_SUPERUSER_SYNC_PASSWORD=False
|
||||||
|
```
|
||||||
|
|
||||||
|
Then start the preview with `./run_preview.sh`. It applies migrations and ensures the
|
||||||
|
admin account exists before starting the server. Existing passwords are preserved;
|
||||||
|
set `DJANGO_SUPERUSER_SYNC_PASSWORD=True` for one start only if you intentionally
|
||||||
|
need to reset the account password. This preview database is separate from the
|
||||||
|
PostgreSQL database used by Docker and production.
|
||||||
|
|
||||||
## Management commands
|
## Management commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -31,9 +31,10 @@ class Command(BaseCommand):
|
|||||||
user.email = email
|
user.email = email
|
||||||
user.is_staff = True
|
user.is_staff = True
|
||||||
user.is_superuser = True
|
user.is_superuser = True
|
||||||
|
user.is_active = True
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
user.save(
|
user.save(
|
||||||
update_fields=["email", "is_staff", "is_superuser", "password"]
|
update_fields=["email", "is_staff", "is_superuser", "is_active", "password"]
|
||||||
)
|
)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
@@ -41,9 +42,16 @@ class Command(BaseCommand):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
fields_to_update = []
|
||||||
|
for field in ("is_staff", "is_superuser", "is_active"):
|
||||||
|
if not getattr(user, field):
|
||||||
|
setattr(user, field, True)
|
||||||
|
fields_to_update.append(field)
|
||||||
|
if fields_to_update:
|
||||||
|
user.save(update_fields=fields_to_update)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
self.style.SUCCESS(
|
self.style.SUCCESS(
|
||||||
f"Admin '{username}' already exists; its password was preserved."
|
f"Admin '{username}' is ready; its password was preserved."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -76,6 +76,24 @@ class EnsureSuperuserCommandTests(TestCase):
|
|||||||
user.refresh_from_db()
|
user.refresh_from_db()
|
||||||
self.assertTrue(user.check_password("changed-in-admin"))
|
self.assertTrue(user.check_password("changed-in-admin"))
|
||||||
|
|
||||||
|
def test_existing_user_regains_admin_access_without_password_reset(self):
|
||||||
|
user = get_user_model().objects.create_user(
|
||||||
|
username="admin", email="admin@com2care.com", password="existing-password"
|
||||||
|
)
|
||||||
|
user.is_active = False
|
||||||
|
user.save(update_fields=["is_active"])
|
||||||
|
environment = {
|
||||||
|
"DJANGO_SUPERUSER_USERNAME": "admin",
|
||||||
|
"DJANGO_SUPERUSER_PASSWORD": "different-password",
|
||||||
|
"DJANGO_SUPERUSER_SYNC_PASSWORD": "False",
|
||||||
|
}
|
||||||
|
with patch.dict(os.environ, environment, clear=False):
|
||||||
|
call_command("ensure_superuser", verbosity=0)
|
||||||
|
|
||||||
|
user.refresh_from_db()
|
||||||
|
self.assertTrue(user.is_active and user.is_staff and user.is_superuser)
|
||||||
|
self.assertTrue(user.check_password("existing-password"))
|
||||||
|
|
||||||
def test_server_operator_can_explicitly_rotate_password(self):
|
def test_server_operator_can_explicitly_rotate_password(self):
|
||||||
user = get_user_model().objects.create_superuser(
|
user = get_user_model().objects.create_superuser(
|
||||||
username="admin",
|
username="admin",
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
"""Persistent local preview database, separate from the production PostgreSQL database."""
|
||||||
|
|
||||||
|
from .development import * # noqa: F401,F403
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
|
"NAME": BASE_DIR / "instance" / "preview.sqlite3",
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
mkdir -p instance
|
||||||
|
|
||||||
|
if [ -f instance/preview_admin.env ]; then
|
||||||
|
set -a
|
||||||
|
. ./instance/preview_admin.env
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DJANGO_SETTINGS_MODULE=config.settings.preview
|
||||||
|
PYTHON=${PYTHON:-venv/bin/python}
|
||||||
|
|
||||||
|
"$PYTHON" manage.py migrate --noinput
|
||||||
|
"$PYTHON" manage.py ensure_superuser
|
||||||
|
exec "$PYTHON" manage.py runserver 127.0.0.1:8000
|
||||||
Reference in New Issue
Block a user