From a4830c74b7cbe13ca12fee628396d84d60c5a9b5 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Thu, 20 Oct 2022 15:58:46 -0300 Subject: [PATCH] Update ical event/user email matching to be case-insensitive --- engine/apps/schedules/ical_utils.py | 11 ++++++----- engine/apps/schedules/tests/test_ical_utils.py | 10 ++++++++++ engine/apps/user_management/apps.py | 16 ++++++++++++++++ engine/apps/user_management/tests/test_user.py | 14 ++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 engine/apps/user_management/apps.py diff --git a/engine/apps/schedules/ical_utils.py b/engine/apps/schedules/ical_utils.py index ac8f9596..3e6756cd 100644 --- a/engine/apps/schedules/ical_utils.py +++ b/engine/apps/schedules/ical_utils.py @@ -42,13 +42,13 @@ def users_in_ical(usernames_from_ical, organization, include_viewers=False): Parse ical file and return list of users found """ # Only grafana username will be used, consider adding grafana email and id - users_found_in_ical = organization.users if not include_viewers: users_found_in_ical = users_found_in_ical.filter(role__in=(Role.ADMIN, Role.EDITOR)) + user_emails = [v.lower() for v in usernames_from_ical] users_found_in_ical = users_found_in_ical.filter( - (Q(username__in=usernames_from_ical) | Q(email__in=usernames_from_ical)) + (Q(username__in=usernames_from_ical) | Q(email__lower__in=user_emails)) ).distinct() # Here is the example how we extracted users previously, using slack fields too @@ -394,8 +394,8 @@ def get_missing_users_from_ical_event(event, organization): all_usernames, _ = get_usernames_from_ical_event(event) users = list(get_users_from_ical_event(event, organization)) found_usernames = [u.username for u in users] - found_emails = [u.email for u in users] - return [u for u in all_usernames if u != "" and u not in found_usernames and u not in found_emails] + found_emails = [u.email.lower() for u in users] + return [u for u in all_usernames if u != "" and u not in found_usernames and u.lower() not in found_emails] def get_users_from_ical_event(event, organization): @@ -536,7 +536,8 @@ def get_user_events_from_calendars(ical_obj: Calendar, calendars: tuple, user: U for component in calendar.walk(): if component.name == "VEVENT": event_user = get_usernames_from_ical_event(component) - if event_user[0][0] in [user.username, user.email]: + event_user_value = event_user[0][0] + if event_user_value == user.username or event_user_value.lower() == user.email.lower(): ical_obj.add_component(component) diff --git a/engine/apps/schedules/tests/test_ical_utils.py b/engine/apps/schedules/tests/test_ical_utils.py index f6bc2155..b1d7171f 100644 --- a/engine/apps/schedules/tests/test_ical_utils.py +++ b/engine/apps/schedules/tests/test_ical_utils.py @@ -15,6 +15,16 @@ from apps.schedules.models import CustomOnCallShift, OnCallScheduleCalendar from common.constants.role import Role +@pytest.mark.django_db +def test_users_in_ical_email_case_insensitive(make_organization_and_user, make_user_for_organization): + organization, user = make_organization_and_user() + user = make_user_for_organization(organization, username="foo", email="TestingUser@test.com") + + usernames = ["testinguser@test.com"] + result = users_in_ical(usernames, organization) + assert set(result) == {user} + + @pytest.mark.django_db @pytest.mark.parametrize( "include_viewers", diff --git a/engine/apps/user_management/apps.py b/engine/apps/user_management/apps.py new file mode 100644 index 00000000..2dd0c259 --- /dev/null +++ b/engine/apps/user_management/apps.py @@ -0,0 +1,16 @@ +from django.apps import AppConfig +from django.db import models + + +# enable a __lower field lookup for email fields +# https://docs.djangoproject.com/en/4.1/howto/custom-lookups/#a-bilateral-transformer-example +class LowerCase(models.Transform): + lookup_name = "lower" + function = "LOWER" + + +class UserManagementConfig(AppConfig): + name = "apps.user_management" + + def ready(self): + models.EmailField.register_lookup(LowerCase) diff --git a/engine/apps/user_management/tests/test_user.py b/engine/apps/user_management/tests/test_user.py index fe615c7c..74440cd1 100644 --- a/engine/apps/user_management/tests/test_user.py +++ b/engine/apps/user_management/tests/test_user.py @@ -2,6 +2,7 @@ import pytest +from apps.user_management.models import User from common.constants.role import Role @@ -22,3 +23,16 @@ def test_self_or_admin( assert admin.self_or_admin(editor, organization) is False assert admin.self_or_admin(second_admin, organization) is True assert admin.self_or_admin(admin_from_another_organization, organization) is False + + +@pytest.mark.django_db +def test_lower_email_filter( + make_organization, + make_user_for_organization, +): + organization = make_organization() + user = make_user_for_organization(organization, email="TestingUser@test.com") + make_user_for_organization(organization, email="testing_user@test.com") + + assert User.objects.get(email__lower="testinguser@test.com") == user + assert User.objects.filter(email__lower__in=["testinguser@test.com"]).get() == user