From 4aa63c74e2deb58a39703bd273e141bd86e65fcc Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Sun, 1 Mar 2026 21:19:12 -0500 Subject: [PATCH] added username (models.CharField) & searchable (models.BooleanField) to User model in lyric app; new ITs confirm functionality here; dashboard views now ensure that sharing a list w. an email address (as opposed to a username) neither confirms nor denies whether that email address has a registered account (ITs green) --- .../dashboard/tests/integrated/test_views.py | 17 +++++++++++++- src/apps/dashboard/views.py | 2 ++ .../0002_user_searchable_user_username.py | 23 +++++++++++++++++++ src/apps/lyric/models.py | 2 ++ .../lyric/tests/integrated/test_models.py | 10 ++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/apps/lyric/migrations/0002_user_searchable_user_username.py diff --git a/src/apps/dashboard/tests/integrated/test_views.py b/src/apps/dashboard/tests/integrated/test_views.py index 796e5e6..30c4586 100644 --- a/src/apps/dashboard/tests/integrated/test_views.py +++ b/src/apps/dashboard/tests/integrated/test_views.py @@ -1,6 +1,7 @@ import lxml.html -from django.test import TestCase +from django.contrib.messages import get_messages +from django.test import override_settings, TestCase from django.urls import reverse from django.utils import html @@ -219,6 +220,20 @@ class ShareListTest(TestCase): data={"recipient": "owner@example.com"}) self.assertNotIn(owner, our_list.shared_with.all()) + @override_settings(MESSAGE_STORAGE='django.contrib.messages.storage.session.SessionStorage') + def test_share_list_shows_privacy_safe_message(self): + our_list = List.objects.create() + response = self.client.post( + f"/dashboard/list/{our_list.id}/share_list", + data={"recipient": "nobody@example.com"}, + follow=True, + ) + messages = list(get_messages(response.wsgi_request)) + self.assertEqual( + str(messages[0]), + "An invite has been sent if that address is registered.", + ) + class ViewAuthListTest(TestCase): def setUp(self): self.owner = User.objects.create(email="disco@example.com") diff --git a/src/apps/dashboard/views.py b/src/apps/dashboard/views.py index cc70d34..fb11257 100644 --- a/src/apps/dashboard/views.py +++ b/src/apps/dashboard/views.py @@ -1,3 +1,4 @@ +from django.contrib import messages from django.http import HttpResponseForbidden from django.shortcuts import redirect, render @@ -56,4 +57,5 @@ def share_list(request, list_id): our_list.shared_with.add(recipient) except User.DoesNotExist: pass + messages.success(request, "An invite has been sent if that address is registered.") return redirect(our_list) diff --git a/src/apps/lyric/migrations/0002_user_searchable_user_username.py b/src/apps/lyric/migrations/0002_user_searchable_user_username.py new file mode 100644 index 0000000..fb4cd9c --- /dev/null +++ b/src/apps/lyric/migrations/0002_user_searchable_user_username.py @@ -0,0 +1,23 @@ +# Generated by Django 6.0 on 2026-03-02 01:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lyric', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='searchable', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='user', + name='username', + field=models.CharField(blank=True, max_length=35, null=True, unique=True), + ), + ] diff --git a/src/apps/lyric/models.py b/src/apps/lyric/models.py index b0ad876..39e798d 100644 --- a/src/apps/lyric/models.py +++ b/src/apps/lyric/models.py @@ -24,6 +24,8 @@ class Token(models.Model): class User(AbstractBaseUser): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) email = models.EmailField(unique=True) + username = models.CharField(max_length=35, unique=True, null=True, blank=True) + searchable = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) diff --git a/src/apps/lyric/tests/integrated/test_models.py b/src/apps/lyric/tests/integrated/test_models.py index 5e3137d..cc4a9fb 100644 --- a/src/apps/lyric/tests/integrated/test_models.py +++ b/src/apps/lyric/tests/integrated/test_models.py @@ -18,6 +18,16 @@ class UserModelTest(TestCase): user = User(id="123") self.assertEqual(user.pk, "123") + def test_user_can_have_a_username(self): + user = User.objects.create(email="a@b.cde") + user.username = "stardust" + user.save() + self.assertEqual(User.objects.get(pk=user.pk).username, "stardust") + + def test_searchable_defaults_to_false(self): + user = User.objects.create(email="a@b.cde") + self.assertFalse(user.searchable) + class TokenModelTest(TestCase): def test_links_user_with_autogen_uid(self): token1 = Token.objects.create(email="a@b.cde")