added superuser support in apps.lyric.admin & new manage.py cmd ensure_superuser; .tests.integrated.test_admin & .test_management_commands green
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -133,11 +133,12 @@
|
|||||||
DJANGO_DEBUG_FALSE: "1"
|
DJANGO_DEBUG_FALSE: "1"
|
||||||
DJANGO_SECRET_KEY: "{{ secret_key.content | b64decode }}"
|
DJANGO_SECRET_KEY: "{{ secret_key.content | b64decode }}"
|
||||||
DJANGO_ALLOWED_HOST: "{{ django_allowed_host }}"
|
DJANGO_ALLOWED_HOST: "{{ django_allowed_host }}"
|
||||||
|
DJANGO_SUPERUSER_EMAIL: "{{ django_superuser_email }}"
|
||||||
|
DJANGO_SUPERUSER_PASSWORD: "{{ django_superuser_password }}"
|
||||||
DATABASE_URL: "postgresql://gamearray:{{ postgres_password }}@gamearray_postgres/gamearray"
|
DATABASE_URL: "postgresql://gamearray:{{ postgres_password }}@gamearray_postgres/gamearray"
|
||||||
MAILGUN_API_KEY: "{{ mailgun_api_key }}"
|
MAILGUN_API_KEY: "{{ mailgun_api_key }}"
|
||||||
CELERY_BROKER_URL: "redis://gamearray_redis:6379/0"
|
CELERY_BROKER_URL: "redis://gamearray_redis:6379/0"
|
||||||
REDIS_URL: "redis://gamearray_redis:6379/1"
|
REDIS_URL: "redis://gamearray_redis:6379/1"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- name: gamearray_net
|
- name: gamearray_net
|
||||||
ports:
|
ports:
|
||||||
@@ -180,6 +181,11 @@
|
|||||||
container: gamearray
|
container: gamearray
|
||||||
command: python manage.py migrate
|
command: python manage.py migrate
|
||||||
|
|
||||||
|
- name: Ensure superuser exists
|
||||||
|
community.docker.docker_container_exec:
|
||||||
|
container: gamearray
|
||||||
|
command: python manage.py ensure_superuser
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
- name: Restart nginx
|
- name: Restart nginx
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ docker run -d --name gamearray_celery \
|
|||||||
echo "==> Running migrations..."
|
echo "==> Running migrations..."
|
||||||
docker exec gamearray python ./manage.py migrate
|
docker exec gamearray python ./manage.py migrate
|
||||||
|
|
||||||
|
echo "==> Ensuring superuser exists..."
|
||||||
|
docker exec gamearray python manage.py ensure_superuser
|
||||||
|
|
||||||
echo "==> Copying static files..."
|
echo "==> Copying static files..."
|
||||||
sudo docker cp gamearray:/src/static/. /var/www/gamearray/static/
|
sudo docker cp gamearray:/src/static/. /var/www/gamearray/static/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
DJANGO_DEBUG_FALSE=1
|
DJANGO_DEBUG_FALSE=1
|
||||||
DJANGO_SECRET_KEY={{ secret_key.content | b64decode }}
|
DJANGO_SECRET_KEY={{ secret_key.content | b64decode }}
|
||||||
DJANGO_ALLOWED_HOST={{ django_allowed_host }}
|
DJANGO_ALLOWED_HOST={{ django_allowed_host }}
|
||||||
|
DJANGO_SUPERUSER_EMAIL={{ django_superuser_email }}
|
||||||
|
DJANGO_SUPERUSER_PASSWORD={{ django_superuser_password }}
|
||||||
DATABASE_URL=postgresql://gamearray:{{ postgres_password }}@gamearray_postgres/gamearray
|
DATABASE_URL=postgresql://gamearray:{{ postgres_password }}@gamearray_postgres/gamearray
|
||||||
MAILGUN_API_KEY={{ mailgun_api_key }}
|
MAILGUN_API_KEY={{ mailgun_api_key }}
|
||||||
CELERY_BROKER_URL=redis://gamearray_redis:6379/0
|
CELERY_BROKER_URL=redis://gamearray_redis:6379/0
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
$ANSIBLE_VAULT;1.1;AES256
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
33616230376431343735626631623932393166343538653732383533323436326335343463646664
|
65383061626464353936363564313761663834646361326362613934363565623234636337313363
|
||||||
6565373531623465613661613533376231373837326438300a393665613839646231633737313938
|
3933313962643261353830333463336166393030313936370a616234626135633432613366633363
|
||||||
64633035336663313163333634623732323537326363646132313136376131636666636538323066
|
61633265363937326231623365646336333737306634646335376135633031643564666164336230
|
||||||
3037373930303537320a313062646166353862633836373466316261363939633433663039323866
|
3435353764383936620a396165386538666433356166383661323037333861373632376432313332
|
||||||
62333739303662343836306538393734343830366336323265393138343438363533353166383031
|
66666236373462363236663335623734633364653539323331396361613738636166323134386466
|
||||||
32313461313137643039376237346633316466646136353038633861333031663164656233366634
|
66656431663261633036333537373336643866623236643139656662333831366435373837656262
|
||||||
38303363383130376264373861393863623330623733643135643461383132613339376633353031
|
36333734376363373462643239623437623735373935633732343639313666663436616630363933
|
||||||
32313863323039646534633733383661333361313832333830383066633130396239626661643264
|
61396530336461393064323161666537646135383462383532363932326132363331633438313138
|
||||||
65636335303339613432326533343337366261356632313639623634386633383836333733663536
|
61623431326537313637626239653038353263313731303262653537316134383264616661623962
|
||||||
39383361353530646166643531333535356636326535383534326237666638326137616162646261
|
32333564366362383431336432303964663835363365636434303332613161363930333065336637
|
||||||
65316466323335653932636338653565383038313531383638393839313736643739363037353230
|
33343466343062306434663765613837343635386630326439303739616166396134393939626434
|
||||||
35653632353531656435396663316537333133653632366437613339303033333536643937353166
|
62336634303963653230626630636363343730623734626336363039623231633532653330646366
|
||||||
64363037653733303332643931343362303261643432366531326262383465313965633064356338
|
66613432633834393133386666623466326131386633303264333766306135623337353433306632
|
||||||
31336333373665373035656533633864316139303934623030383934393434356334643962666163
|
66323733373232383862646661313966366465333463366361366337656537623562613964666631
|
||||||
33343739366336613263333764306365333566363536616662383733616237396563346132336633
|
65373566316432383134666434393338626138363632633766636561383263333636623530326664
|
||||||
38663239613339376335386233386330396634323033343332366130616162666339393861306336
|
63333265366132376437396431393535323931383637323833303839336635633735333565333530
|
||||||
35383566383831356530633130313732356331616164646132626665646235396635386237313538
|
65343263373630633063383931646163323237643436366566363932646566323539373136646433
|
||||||
38656631336261646530303761643334303937613036363766303637376262373466316431323731
|
37623638333834373537316164633166633738333363656431356163623332396631353864333333
|
||||||
38666462313639353131303134646434646135366136343361353932326165626666306361393431
|
33306666646532626636376239326438373737383432663539333736363866663938396136383035
|
||||||
62646238323265346263386363373462313766616333326366366461346436383064336535376339
|
32343534613862653538346430313338326435356230636535343464666262626663376635363835
|
||||||
31356566356336386262393831616631666233633930393263623563386265343237323133313832
|
65363862663461353464313533313333323863313539643533343431643130383663656161616131
|
||||||
3430363635363332303963316530663765613666306233376463
|
33323639333564383830346163386362386238323936393832623961646565613961356263356365
|
||||||
|
65376431666130356564666236383764316136326366666661326538653133343165326431393564
|
||||||
|
36303065366263316232663230343137333231346538633036613066643365616331336135376461
|
||||||
|
35613265623134663633303238366363336137383436663836353863623533396236666433303738
|
||||||
|
38356361653633323065303035376664326238633066623731623436333332373363636634323433
|
||||||
|
393631303539373234386465663630316335
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Token, User
|
from .models import Token, User
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(User)
|
class UserAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["email"]
|
||||||
|
search_fields = ["email"]
|
||||||
|
|
||||||
|
admin.site.register(User, UserAdmin)
|
||||||
admin.site.register(Token)
|
admin.site.register(Token)
|
||||||
|
|||||||
0
src/apps/lyric/management/__init__.py
Normal file
0
src/apps/lyric/management/__init__.py
Normal file
0
src/apps/lyric/management/commands/__init__.py
Normal file
0
src/apps/lyric/management/commands/__init__.py
Normal file
21
src/apps/lyric/management/commands/ensure_superuser.py
Normal file
21
src/apps/lyric/management/commands/ensure_superuser.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from apps.lyric.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Create a superuser if none exists"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
if User.objects.filter(is_superuser=True).exists():
|
||||||
|
self.stdout.write("Superuser already exists!")
|
||||||
|
return
|
||||||
|
email = os.environ.get('DJANGO_SUPERUSER_EMAIL')
|
||||||
|
password = os.environ.get('DJANGO_SUPERUSER_PASSWORD')
|
||||||
|
if not email or not password:
|
||||||
|
self.stdout.write("Superuser credentials not set!—skipping")
|
||||||
|
return
|
||||||
|
User.objects.create_superuser(email=email, password=password)
|
||||||
|
self.stdout.write("Superuser created!")
|
||||||
25
src/apps/lyric/tests/integrated/test_admin.py
Normal file
25
src/apps/lyric/tests/integrated/test_admin.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from apps.lyric.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class UserAdminTest(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.superuser = User.objects.create_superuser(
|
||||||
|
email="admin@example.com", password="secret"
|
||||||
|
)
|
||||||
|
self.client.force_login(self.superuser)
|
||||||
|
|
||||||
|
def test_user_changelist_loads(self):
|
||||||
|
response = self.client.get("/admin/lyric/user/")
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_user_changelist_displays_email(self):
|
||||||
|
response = self.client.get("/admin/lyric/user/")
|
||||||
|
self.assertContains(response, "admin@example.com")
|
||||||
|
|
||||||
|
def test_user_changelist_search_by_email(self):
|
||||||
|
User.objects.create_superuser(email="other@example.com", password="x")
|
||||||
|
response = self.client.get("/admin/lyric/user/?q=admin")
|
||||||
|
self.assertContains(response, "admin@example.com")
|
||||||
|
self.assertNotContains(response, "other@example.com")
|
||||||
34
src/apps/lyric/tests/integrated/test_management_commands.py
Normal file
34
src/apps/lyric/tests/integrated/test_management_commands.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.test import TestCase
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
# from apps.lyric.management.commands.ensure_superuser import EnsureSuperuserCommand
|
||||||
|
from apps.lyric.models import User
|
||||||
|
|
||||||
|
|
||||||
|
FAKE_ENV = {
|
||||||
|
'DJANGO_SUPERUSER_EMAIL': 'admin@example.com',
|
||||||
|
'DJANGO_SUPERUSER_PASSWORD': 'secret',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class EnsureSuperuserCommandTest(TestCase):
|
||||||
|
def test_creates_superuser_if_none_exists(self):
|
||||||
|
with patch.dict('os.environ', FAKE_ENV):
|
||||||
|
call_command('ensure_superuser')
|
||||||
|
self.assertEqual(User.objects.filter(is_superuser=True).count(), 1)
|
||||||
|
|
||||||
|
def test_does_not_create_duplicate_if_superuser_exists(self):
|
||||||
|
User.objects.create_superuser(email="admin@example.com", password="secret")
|
||||||
|
with patch.dict('os.environ', FAKE_ENV):
|
||||||
|
call_command('ensure_superuser')
|
||||||
|
self.assertEqual(User.objects.filter(is_superuser=True).count(), 1)
|
||||||
|
|
||||||
|
def test_skips_creation_if_credentials_not_set(self):
|
||||||
|
with patch.dict("os.environ", {}):
|
||||||
|
os.environ.pop("DJANGO_SUPERUSER_EMAIL", None)
|
||||||
|
os.environ.pop("DJANGO_SUPERUSER_PASSWORD", None)
|
||||||
|
call_command("ensure_superuser")
|
||||||
|
self.assertEqual(User.objects.filter(is_superuser=True).count(), 0)
|
||||||
Reference in New Issue
Block a user