From 510da219347f8e267a3422e6d34e0810b5acaee7 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 18 Jan 2024 19:58:53 -0500 Subject: [PATCH 1/7] Implement VIP table and fix 401 login bug --- src/djangooidc/exceptions.py | 4 ++ src/djangooidc/oidc.py | 7 ++++ src/djangooidc/tests/test_views.py | 19 ++++++++++ src/djangooidc/views.py | 8 ++++ src/registrar/admin.py | 23 ++++++++++++ .../migrations/0063_veryimportantperson.py | 37 +++++++++++++++++++ src/registrar/models/__init__.py | 3 ++ src/registrar/models/user.py | 5 +++ src/registrar/models/very_important_person.py | 36 ++++++++++++++++++ src/registrar/tests/test_admin.py | 25 +++++++++++++ src/registrar/tests/test_models.py | 9 ++++- 11 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/registrar/migrations/0063_veryimportantperson.py create mode 100644 src/registrar/models/very_important_person.py diff --git a/src/djangooidc/exceptions.py b/src/djangooidc/exceptions.py index 260750a4d..226337f54 100644 --- a/src/djangooidc/exceptions.py +++ b/src/djangooidc/exceptions.py @@ -33,6 +33,10 @@ class AuthenticationFailed(OIDCException): friendly_message = "This login attempt didn't work." +class NoStateDefined(OIDCException): + friendly_message = "The session state is None." + + class InternalError(OIDCException): status = status.INTERNAL_SERVER_ERROR friendly_message = "The system broke while trying to log you in." diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 91bfddc66..bff766bb4 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -183,6 +183,8 @@ class Client(oic.Client): if authn_response["state"] != session.get("state", None): # this most likely means the user's Django session vanished logger.error("Received state not the same as expected for %s" % state) + if session.get("state", None) is None: + raise o_e.NoStateDefined() raise o_e.AuthenticationFailed(locator=state) if self.behaviour.get("response_type") == "code": @@ -272,6 +274,11 @@ class Client(oic.Client): super(Client, self).store_response(resp, info) + def get_default_acr_value(self): + """returns the acr_value from settings + this helper function is called from djangooidc views""" + return self.behaviour.get("acr_value") + def get_step_up_acr_value(self): """returns the step_up_acr_value from settings this helper function is called from djangooidc views""" diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index 282e91e1f..63b23df96 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -3,6 +3,8 @@ from unittest.mock import MagicMock, patch from django.http import HttpResponse from django.test import Client, TestCase, RequestFactory from django.urls import reverse + +from djangooidc.exceptions import NoStateDefined from ..views import login_callback from .common import less_console_noise @@ -17,6 +19,9 @@ class ViewsTest(TestCase): def say_hi(*args): return HttpResponse("Hi") + def create_acr(*args): + return "any string" + def user_info(*args): return { "sub": "TEST", @@ -34,6 +39,7 @@ class ViewsTest(TestCase): callback_url = reverse("openid_login_callback") # mock mock_client.create_authn_request.side_effect = self.say_hi + mock_client.get_default_acr_value.side_effect = self.create_acr # test response = self.client.get(reverse("login"), {"next": callback_url}) # assert @@ -53,6 +59,19 @@ class ViewsTest(TestCase): self.assertTemplateUsed(response, "500.html") self.assertIn("Server error", response.content.decode("utf-8")) + def test_callback_with_no_session_state(self, mock_client): + """If the local session is None (ie the server restarted while user was logged out), + we do not throw an exception. Rather, we attempt to login again.""" + # mock + mock_client.get_default_acr_value.side_effect = self.create_acr + mock_client.callback.side_effect = NoStateDefined() + # test + with less_console_noise(): + response = self.client.get(reverse("openid_login_callback")) + # assert + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, "/") + def test_login_callback_reads_next(self, mock_client): # setup session = self.client.session diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index b5905df48..b786ed2e9 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -55,6 +55,10 @@ def error_page(request, error): def openid(request): """Redirect the user to an authentication provider (OP).""" + + # If the session reset because of a server restart, attempt to login again + request.session["acr_value"] = CLIENT.get_default_acr_value() + request.session["next"] = request.GET.get("next", "/") try: @@ -78,9 +82,13 @@ def login_callback(request): if user: login(request, user) logger.info("Successfully logged in user %s" % user) + # Double login bug? return redirect(request.session.get("next", "/")) else: raise o_e.BannedUser() + except o_e.NoStateDefined as nsd_err: + logger.debug(f"No State Defined: {nsd_err}") + return redirect(request.session.get("next", "/")) except Exception as err: return error_page(request, err) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 8d3b1d29f..9ad459a06 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1239,6 +1239,28 @@ class DraftDomainAdmin(ListHeaderAdmin): search_help_text = "Search by draft domain name." +class VeryImportantPersonAdmin(ListHeaderAdmin): + list_display = ("email", "custom_user_label", "notes", "created_at") + search_fields = ["email"] + search_help_text = "Search by email." + list_filter = [ + "user", + ] + readonly_fields = [ + "user", + ] + + def custom_user_label(self, obj): + return obj.user + + custom_user_label.short_description = "Requestor" # type: ignore + + def save_model(self, request, obj, form, change): + # Set the user field to the current admin user + obj.user = request.user if request.user.is_authenticated else None + super().save_model(request, obj, form, change) + + admin.site.unregister(LogEntry) # Unregister the default registration admin.site.register(LogEntry, CustomLogEntryAdmin) admin.site.register(models.User, MyUserAdmin) @@ -1259,3 +1281,4 @@ admin.site.register(models.Website, WebsiteAdmin) admin.site.register(models.PublicContact, AuditedAdmin) admin.site.register(models.DomainApplication, DomainApplicationAdmin) admin.site.register(models.TransitionDomain, TransitionDomainAdmin) +admin.site.register(models.VeryImportantPerson, VeryImportantPersonAdmin) diff --git a/src/registrar/migrations/0063_veryimportantperson.py b/src/registrar/migrations/0063_veryimportantperson.py new file mode 100644 index 000000000..3d56ae1ac --- /dev/null +++ b/src/registrar/migrations/0063_veryimportantperson.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.7 on 2024-01-19 00:18 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0062_alter_host_name"), + ] + + operations = [ + migrations.CreateModel( + name="VeryImportantPerson", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("email", models.EmailField(blank=True, db_index=True, help_text="Email", max_length=254, null=True)), + ("notes", models.TextField(blank=True, help_text="Notes", null=True)), + ( + "user", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="verifiedby_user", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/src/registrar/models/__init__.py b/src/registrar/models/__init__.py index 6afad5a5c..90cb2e286 100644 --- a/src/registrar/models/__init__.py +++ b/src/registrar/models/__init__.py @@ -13,6 +13,7 @@ from .user import User from .user_group import UserGroup from .website import Website from .transition_domain import TransitionDomain +from .very_important_person import VeryImportantPerson __all__ = [ "Contact", @@ -29,6 +30,7 @@ __all__ = [ "UserGroup", "Website", "TransitionDomain", + "VeryImportantPerson", ] auditlog.register(Contact) @@ -45,3 +47,4 @@ auditlog.register(User, m2m_fields=["user_permissions", "groups"]) auditlog.register(UserGroup, m2m_fields=["permissions"]) auditlog.register(Website) auditlog.register(TransitionDomain) +auditlog.register(VeryImportantPerson) diff --git a/src/registrar/models/user.py b/src/registrar/models/user.py index d79e4c9ee..269569bfe 100644 --- a/src/registrar/models/user.py +++ b/src/registrar/models/user.py @@ -7,6 +7,7 @@ from registrar.models.user_domain_role import UserDomainRole from .domain_invitation import DomainInvitation from .transition_domain import TransitionDomain +from .very_important_person import VeryImportantPerson from .domain import Domain from phonenumber_field.modelfields import PhoneNumberField # type: ignore @@ -89,6 +90,10 @@ class User(AbstractUser): if TransitionDomain.objects.filter(username=email).exists(): return False + # New users flagged by Staff to bypass ial2 + if VeryImportantPerson.objects.filter(email=email).exists(): + return False + # A new incoming user who is being invited to be a domain manager (that is, # their email address is in DomainInvitation for an invitation that is not yet "retrieved"). invited = DomainInvitation.DomainInvitationStatus.INVITED diff --git a/src/registrar/models/very_important_person.py b/src/registrar/models/very_important_person.py new file mode 100644 index 000000000..42621c64a --- /dev/null +++ b/src/registrar/models/very_important_person.py @@ -0,0 +1,36 @@ +from django.db import models + +from .utility.time_stamped_model import TimeStampedModel + + +class VeryImportantPerson(TimeStampedModel): + + """""" + + email = models.EmailField( + null=True, + blank=True, + help_text="Email", + db_index=True, + ) + + user = models.ForeignKey( + "registrar.User", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="verifiedby_user", + ) + + notes = models.TextField( + null=True, + blank=True, + help_text="Notes", + ) + + def __str__(self): + try: + if self.email: + return self.email + except Exception: + return "" diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index f7b1ef06e..175bef11f 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -14,9 +14,11 @@ from registrar.admin import ( ContactAdmin, DomainInformationAdmin, UserDomainRoleAdmin, + VeryImportantPersonAdmin, ) from registrar.models import Domain, DomainApplication, DomainInformation, User, DomainInvitation, Contact, Website from registrar.models.user_domain_role import UserDomainRole +from registrar.models.very_important_person import VeryImportantPerson from .common import ( MockSESClient, AuditedAdminMockData, @@ -1737,3 +1739,26 @@ class ContactAdminTest(TestCase): def tearDown(self): User.objects.all().delete() + + +class VeryImportantPersonAdminTestCase(TestCase): + def setUp(self): + self.superuser = create_superuser() + self.factory = RequestFactory() + + def test_save_model_sets_user_field(self): + # Create an instance of the admin class + admin_instance = VeryImportantPersonAdmin(model=VeryImportantPerson, admin_site=None) + + # Create a VeryImportantPerson instance + vip_instance = VeryImportantPerson(email="test@example.com", notes="Test Notes") + + # Create a request object + request = self.factory.post("/admin/yourapp/veryimportantperson/add/") + request.user = self.superuser + + # Call the save_model method + admin_instance.save_model(request, vip_instance, None, None) + + # Check that the user field is set to the request.user + self.assertEqual(vip_instance.user, self.superuser) diff --git a/src/registrar/tests/test_models.py b/src/registrar/tests/test_models.py index 464d00dc5..ef6522747 100644 --- a/src/registrar/tests/test_models.py +++ b/src/registrar/tests/test_models.py @@ -15,7 +15,8 @@ from registrar.models import ( ) import boto3_mocking -from registrar.models.transition_domain import TransitionDomain # type: ignore +from registrar.models.transition_domain import TransitionDomain +from registrar.models.very_important_person import VeryImportantPerson # type: ignore from .common import MockSESClient, less_console_noise, completed_application from django_fsm import TransitionNotAllowed @@ -652,6 +653,12 @@ class TestUser(TestCase): TransitionDomain.objects.get_or_create(username=self.user.email, domain_name=self.domain_name) self.assertFalse(User.needs_identity_verification(self.user.email, self.user.username)) + def test_identity_verification_with_very_important_person(self): + """A Very Important Person should return False + when tested with class method needs_identity_verification""" + VeryImportantPerson.objects.get_or_create(email=self.user.email) + self.assertFalse(User.needs_identity_verification(self.user.email, self.user.username)) + def test_identity_verification_with_invited_user(self): """An invited user should return False when tested with class method needs_identity_verification""" From d1a80d3307d95dfd042ce841b5424ea3ca630ddf Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Fri, 19 Jan 2024 15:22:42 -0500 Subject: [PATCH 2/7] revert column header to user, truncate notes --- src/registrar/admin.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 9ad459a06..125ff2e8a 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1240,7 +1240,7 @@ class DraftDomainAdmin(ListHeaderAdmin): class VeryImportantPersonAdmin(ListHeaderAdmin): - list_display = ("email", "custom_user_label", "notes", "created_at") + list_display = ("email", "user", "truncated_notes", "created_at") search_fields = ["email"] search_help_text = "Search by email." list_filter = [ @@ -1250,10 +1250,11 @@ class VeryImportantPersonAdmin(ListHeaderAdmin): "user", ] - def custom_user_label(self, obj): - return obj.user + def truncated_notes(self, obj): + # Truncate the 'notes' field to 200 characters + return str(obj.notes)[:50] - custom_user_label.short_description = "Requestor" # type: ignore + truncated_notes.short_description = "Notes (Truncated)" # type: ignore def save_model(self, request, obj, form, change): # Set the user field to the current admin user From 3f8e5ce204516eb54fda3b96e7ed6c4631808ebb Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 23 Jan 2024 18:15:56 -0500 Subject: [PATCH 3/7] Revisions on model --- src/djangooidc/views.py | 4 ++-- src/registrar/admin.py | 8 ++++---- src/registrar/migrations/0063_veryimportantperson.py | 8 ++++---- src/registrar/models/very_important_person.py | 12 ++++-------- src/registrar/tests/test_admin.py | 4 ++-- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index b786ed2e9..2fc2a0363 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -82,12 +82,12 @@ def login_callback(request): if user: login(request, user) logger.info("Successfully logged in user %s" % user) - # Double login bug? + # Double login bug (1507)? return redirect(request.session.get("next", "/")) else: raise o_e.BannedUser() except o_e.NoStateDefined as nsd_err: - logger.debug(f"No State Defined: {nsd_err}") + logger.warning(f"No State Defined: {nsd_err}") return redirect(request.session.get("next", "/")) except Exception as err: return error_page(request, err) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 125ff2e8a..eee808691 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1240,14 +1240,14 @@ class DraftDomainAdmin(ListHeaderAdmin): class VeryImportantPersonAdmin(ListHeaderAdmin): - list_display = ("email", "user", "truncated_notes", "created_at") + list_display = ("email", "requestor", "truncated_notes", "created_at") search_fields = ["email"] search_help_text = "Search by email." list_filter = [ - "user", + "requestor", ] readonly_fields = [ - "user", + "requestor", ] def truncated_notes(self, obj): @@ -1258,7 +1258,7 @@ class VeryImportantPersonAdmin(ListHeaderAdmin): def save_model(self, request, obj, form, change): # Set the user field to the current admin user - obj.user = request.user if request.user.is_authenticated else None + obj.requestor = request.requestor if request.requestor.is_authenticated else None super().save_model(request, obj, form, change) diff --git a/src/registrar/migrations/0063_veryimportantperson.py b/src/registrar/migrations/0063_veryimportantperson.py index 3d56ae1ac..29ea7ffdb 100644 --- a/src/registrar/migrations/0063_veryimportantperson.py +++ b/src/registrar/migrations/0063_veryimportantperson.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2024-01-19 00:18 +# Generated by Django 4.2.7 on 2024-01-23 21:02 from django.conf import settings from django.db import migrations, models @@ -17,10 +17,10 @@ class Migration(migrations.Migration): ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), - ("email", models.EmailField(blank=True, db_index=True, help_text="Email", max_length=254, null=True)), - ("notes", models.TextField(blank=True, help_text="Notes", null=True)), + ("email", models.EmailField(blank=True, db_index=True, help_text="Email", max_length=254)), + ("notes", models.TextField(blank=True, help_text="Notes")), ( - "user", + "requestor", models.ForeignKey( blank=True, null=True, diff --git a/src/registrar/models/very_important_person.py b/src/registrar/models/very_important_person.py index 42621c64a..2fb53ff27 100644 --- a/src/registrar/models/very_important_person.py +++ b/src/registrar/models/very_important_person.py @@ -8,13 +8,13 @@ class VeryImportantPerson(TimeStampedModel): """""" email = models.EmailField( - null=True, + null=False, blank=True, help_text="Email", db_index=True, ) - user = models.ForeignKey( + requestor = models.ForeignKey( "registrar.User", null=True, blank=True, @@ -23,14 +23,10 @@ class VeryImportantPerson(TimeStampedModel): ) notes = models.TextField( - null=True, + null=False, blank=True, help_text="Notes", ) def __str__(self): - try: - if self.email: - return self.email - except Exception: - return "" + return self.email diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 175bef11f..139e4bc84 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -1755,10 +1755,10 @@ class VeryImportantPersonAdminTestCase(TestCase): # Create a request object request = self.factory.post("/admin/yourapp/veryimportantperson/add/") - request.user = self.superuser + request.requestor = self.superuser # Call the save_model method admin_instance.save_model(request, vip_instance, None, None) # Check that the user field is set to the request.user - self.assertEqual(vip_instance.user, self.superuser) + self.assertEqual(vip_instance.requestor, self.superuser) From 52b76a79981a63b03721664c699bf57c2b6d0e5e Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 23 Jan 2024 18:40:21 -0500 Subject: [PATCH 4/7] fix error in admin.py --- src/registrar/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index eee808691..dedc6f527 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1258,7 +1258,7 @@ class VeryImportantPersonAdmin(ListHeaderAdmin): def save_model(self, request, obj, form, change): # Set the user field to the current admin user - obj.requestor = request.requestor if request.requestor.is_authenticated else None + obj.requestor = request.user if request.user.is_authenticated else None super().save_model(request, obj, form, change) From 784b187b09add07857c1975049560be1e520e44f Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 23 Jan 2024 18:48:51 -0500 Subject: [PATCH 5/7] fix failing test by force logging in user --- src/registrar/tests/test_admin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 139e4bc84..e0d0a6be5 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -1747,6 +1747,8 @@ class VeryImportantPersonAdminTestCase(TestCase): self.factory = RequestFactory() def test_save_model_sets_user_field(self): + self.client.force_login(self.superuser) + # Create an instance of the admin class admin_instance = VeryImportantPersonAdmin(model=VeryImportantPerson, admin_site=None) From 8570a03600dc8b00ff271e527514376b1ec48370 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 23 Jan 2024 18:58:26 -0500 Subject: [PATCH 6/7] Make email and notes required, fix unit test --- src/registrar/migrations/0063_veryimportantperson.py | 6 +++--- src/registrar/models/very_important_person.py | 4 ++-- src/registrar/tests/test_admin.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/registrar/migrations/0063_veryimportantperson.py b/src/registrar/migrations/0063_veryimportantperson.py index 29ea7ffdb..38cfe328e 100644 --- a/src/registrar/migrations/0063_veryimportantperson.py +++ b/src/registrar/migrations/0063_veryimportantperson.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2024-01-23 21:02 +# Generated by Django 4.2.7 on 2024-01-23 23:51 from django.conf import settings from django.db import migrations, models @@ -17,8 +17,8 @@ class Migration(migrations.Migration): ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), - ("email", models.EmailField(blank=True, db_index=True, help_text="Email", max_length=254)), - ("notes", models.TextField(blank=True, help_text="Notes")), + ("email", models.EmailField(db_index=True, help_text="Email", max_length=254)), + ("notes", models.TextField(help_text="Notes")), ( "requestor", models.ForeignKey( diff --git a/src/registrar/models/very_important_person.py b/src/registrar/models/very_important_person.py index 2fb53ff27..3d6430251 100644 --- a/src/registrar/models/very_important_person.py +++ b/src/registrar/models/very_important_person.py @@ -9,7 +9,7 @@ class VeryImportantPerson(TimeStampedModel): email = models.EmailField( null=False, - blank=True, + blank=False, help_text="Email", db_index=True, ) @@ -24,7 +24,7 @@ class VeryImportantPerson(TimeStampedModel): notes = models.TextField( null=False, - blank=True, + blank=False, help_text="Notes", ) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index e0d0a6be5..7c9aa8fe4 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -1748,7 +1748,7 @@ class VeryImportantPersonAdminTestCase(TestCase): def test_save_model_sets_user_field(self): self.client.force_login(self.superuser) - + # Create an instance of the admin class admin_instance = VeryImportantPersonAdmin(model=VeryImportantPerson, admin_site=None) @@ -1757,7 +1757,7 @@ class VeryImportantPersonAdminTestCase(TestCase): # Create a request object request = self.factory.post("/admin/yourapp/veryimportantperson/add/") - request.requestor = self.superuser + request.user = self.superuser # Call the save_model method admin_instance.save_model(request, vip_instance, None, None) From e88c50c173a9613fa9cea2ceaf5138d48617e9fb Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 24 Jan 2024 13:11:00 -0500 Subject: [PATCH 7/7] add class description for vip --- src/registrar/admin.py | 2 +- src/registrar/models/very_important_person.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index dedc6f527..d64296e56 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1251,7 +1251,7 @@ class VeryImportantPersonAdmin(ListHeaderAdmin): ] def truncated_notes(self, obj): - # Truncate the 'notes' field to 200 characters + # Truncate the 'notes' field to 50 characters return str(obj.notes)[:50] truncated_notes.short_description = "Notes (Truncated)" # type: ignore diff --git a/src/registrar/models/very_important_person.py b/src/registrar/models/very_important_person.py index 3d6430251..9134cb893 100644 --- a/src/registrar/models/very_important_person.py +++ b/src/registrar/models/very_important_person.py @@ -5,7 +5,7 @@ from .utility.time_stamped_model import TimeStampedModel class VeryImportantPerson(TimeStampedModel): - """""" + """emails that get added to this table will bypass ial2 on login.""" email = models.EmailField( null=False,