Browse Source

ref(hc): Make new NotificationSettingsSerializer the default (#53073)

Now that the frontend side has been rolled out and is using the v2
serializer, make it the default one.

---------

Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
Zach Collins 1 year ago
parent
commit
f5ab555469

+ 0 - 1
pyproject.toml

@@ -359,7 +359,6 @@ module = [
     "sentry.api.serializers.models.integration",
     "sentry.api.serializers.models.integration_feature",
     "sentry.api.serializers.models.notification_action",
-    "sentry.api.serializers.models.notification_setting",
     "sentry.api.serializers.models.organization",
     "sentry.api.serializers.models.organization_member.base",
     "sentry.api.serializers.models.plugin",

+ 1 - 7
src/sentry/api/endpoints/team_notification_settings_details.py

@@ -6,9 +6,6 @@ from sentry.api.base import region_silo_endpoint
 from sentry.api.bases.team import TeamEndpoint
 from sentry.api.serializers import serialize
 from sentry.api.serializers.models.notification_setting import NotificationSettingsSerializer
-from sentry.api.serializers.models.notification_setting2 import (
-    NotificationSettingsSerializer as NotificationSettingsSerializerV2,
-)
 from sentry.api.validators.notifications import validate, validate_type_option
 from sentry.models import NotificationSetting, Team
 
@@ -30,15 +27,12 @@ class TeamNotificationSettingsDetailsEndpoint(TeamEndpoint):
         """
 
         type_option = validate_type_option(request.GET.get("type"))
-        v2_serializer = request.GET.get("v2") == "serializer"
 
         return Response(
             serialize(
                 team,
                 request.user,
-                NotificationSettingsSerializerV2()
-                if v2_serializer
-                else NotificationSettingsSerializer(),
+                NotificationSettingsSerializer(),
                 type=type_option,
             ),
         )

+ 1 - 7
src/sentry/api/endpoints/user_notification_settings_details.py

@@ -6,9 +6,6 @@ from sentry.api.base import control_silo_endpoint
 from sentry.api.bases.user import UserEndpoint
 from sentry.api.serializers import serialize
 from sentry.api.serializers.models.notification_setting import NotificationSettingsSerializer
-from sentry.api.serializers.models.notification_setting2 import (
-    NotificationSettingsSerializer as NotificationSettingsSerializerV2,
-)
 from sentry.api.validators.notifications import validate, validate_type_option
 from sentry.models import NotificationSetting, User
 
@@ -34,14 +31,11 @@ class UserNotificationSettingsDetailsEndpoint(UserEndpoint):
         """
 
         type_option = validate_type_option(request.GET.get("type"))
-        v2_serializer = request.GET.get("v2") == "serializer"
 
         notification_preferences = serialize(
             user,
             request.user,
-            NotificationSettingsSerializerV2()
-            if v2_serializer
-            else NotificationSettingsSerializer(),
+            NotificationSettingsSerializer(),
             type=type_option,
         )
 

+ 19 - 48
src/sentry/api/serializers/models/notification_setting.py

@@ -1,18 +1,11 @@
-"""
-Deprecated.  Usage of notification_setting2 will be swapped in after a 3 step commit refactoring is done.  This
-implementation is being used currently but any new features implemented here will be removed once notification_setting2
-can be fully deployed.
-"""
 from collections import defaultdict
-from typing import Any, Iterable, Mapping, MutableMapping, Optional, Union
+from typing import Any, Iterable, Mapping, MutableMapping, Optional, Set, Union
 
 from sentry.api.serializers import Serializer
 from sentry.models.notificationsetting import NotificationSetting
 from sentry.models.team import Team
 from sentry.models.user import User
-from sentry.notifications.helpers import get_fallback_settings
-from sentry.notifications.types import VALID_VALUES_FOR_KEY, NotificationSettingTypes
-from sentry.services.hybrid_cloud.actor import RpcActor
+from sentry.notifications.types import NotificationSettingTypes
 from sentry.services.hybrid_cloud.organization import RpcTeam
 from sentry.services.hybrid_cloud.user import RpcUser
 
@@ -29,7 +22,7 @@ class NotificationSettingsSerializer(Serializer):
         item_list: Iterable[Union["Team", "User"]],
         user: User,
         **kwargs: Any,
-    ) -> Mapping[Union["Team", "User"], Mapping[str, Iterable[Any]]]:
+    ) -> MutableMapping[Union["Team", "User"], MutableMapping[str, Set[Any]]]:
         """
         This takes a list of recipients (which are either Users or Teams,
         because both can have Notification Settings). The function
@@ -53,38 +46,30 @@ class NotificationSettingsSerializer(Serializer):
             user_ids=list(user_map.keys()),
         )
 
-        result: MutableMapping[
-            Union["Team", "User"], MutableMapping[str, Iterable[Any]]
-        ] = defaultdict(lambda: defaultdict(set))
+        result: MutableMapping[Union[Team, User], MutableMapping[str, Set[Any]]] = defaultdict(
+            lambda: defaultdict(set)
+        )
+        for _, team in team_map.items():
+            result[team]["settings"] = set()
+        for _, user in user_map.items():
+            result[user]["settings"] = set()
 
         for notifications_setting in notifications_settings:
-            target = None
             if notifications_setting.user_id:
-                target = user_map[notifications_setting.user_id]
-            if notifications_setting.team_id:
-                target = team_map[notifications_setting.team_id]
-            if target:
-                result[target]["settings"].add(notifications_setting)
+                target_user = user_map[notifications_setting.user_id]
+                result[target_user]["settings"].add(notifications_setting)
+            elif notifications_setting.team_id:
+                target_team = team_map[notifications_setting.team_id]
+                result[target_team]["settings"].add(notifications_setting)
             else:
                 raise ValueError(
                     f"NotificationSetting {notifications_setting.id} has neither team_id nor user_id"
                 )
-
-        for recipient in item_list:
-            # This works because both User and Team models implement `get_projects`.
-            result[recipient]["projects"] = recipient.get_projects()
-
-            if isinstance(recipient, Team):
-                result[recipient]["organizations"] = {recipient.organization}
-
-            if isinstance(recipient, User):
-                result[recipient]["organizations"] = user.get_orgs()
-
         return result
 
     def serialize(
         self,
-        obj: Union["Team", "User"],
+        obj: Union[Team, User],
         attrs: Mapping[str, Iterable[Any]],
         user: User,
         **kwargs: Any,
@@ -115,27 +100,13 @@ class NotificationSettingsSerializer(Serializer):
         :param kwargs: The same `kwargs` as `get_attrs`.
         :returns A mapping. See example.
         """
-        type_option: Optional[NotificationSettingTypes] = kwargs.get("type")
-        types_to_serialize = {type_option} if type_option else set(VALID_VALUES_FOR_KEY.keys())
-
-        project_ids = {_.id for _ in attrs["projects"]}
-        organization_ids = {_.id for _ in attrs["organizations"]}
 
-        data = get_fallback_settings(
-            types_to_serialize,
-            project_ids,
-            organization_ids,
-            recipient=RpcActor.from_object(obj),
-        )
+        data: MutableMapping[
+            str, MutableMapping[str, MutableMapping[int, MutableMapping[str, str]]]
+        ] = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
 
         # Forgive the variable name, I wanted the following lines to be legible.
         for n in attrs["settings"]:
-            # Filter out invalid notification settings.
-            if (n.scope_str == "project" and n.scope_identifier not in project_ids) or (
-                n.scope_str == "organization" and n.scope_identifier not in organization_ids
-            ):
-                continue
-
             # Override the notification settings.
             data[n.type_str][n.scope_str][n.scope_identifier][n.provider_str] = n.value_str
         return data

+ 0 - 112
src/sentry/api/serializers/models/notification_setting2.py

@@ -1,112 +0,0 @@
-from collections import defaultdict
-from typing import Any, Iterable, Mapping, MutableMapping, Optional, Set, Union
-
-from sentry.api.serializers import Serializer
-from sentry.models.notificationsetting import NotificationSetting
-from sentry.models.team import Team
-from sentry.models.user import User
-from sentry.notifications.types import NotificationSettingTypes
-from sentry.services.hybrid_cloud.organization import RpcTeam
-from sentry.services.hybrid_cloud.user import RpcUser
-
-
-class NotificationSettingsSerializer(Serializer):
-    """
-    This Serializer fetches and serializes NotificationSettings for a list of
-    targets (users or teams.) Pass filters like `project=project` and
-    `type=NotificationSettingTypes.DEPLOY` to kwargs.
-    """
-
-    def get_attrs(
-        self,
-        item_list: Iterable[Union["Team", "User"]],
-        user: User,
-        **kwargs: Any,
-    ) -> MutableMapping[Union["Team", "User"], MutableMapping[str, Set[Any]]]:
-        """
-        This takes a list of recipients (which are either Users or Teams,
-        because both can have Notification Settings). The function
-        returns a mapping of targets to flat lists of object to be passed to the
-        `serialize` function.
-
-        :param item_list: Either a Set of User or Team objects whose
-            notification settings should be serialized.
-        :param user: The user who will be viewing the notification settings.
-        :param kwargs: Dict of optional filter options:
-            - type: NotificationSettingTypes enum value. e.g. WORKFLOW, DEPLOY.
-        """
-        type_option: Optional[NotificationSettingTypes] = kwargs.get("type")
-
-        team_map = {t.id: t for t in item_list if isinstance(t, (Team, RpcTeam))}
-        user_map = {u.id: u for u in item_list if isinstance(u, (User, RpcUser))}
-
-        notifications_settings = NotificationSetting.objects._filter(
-            type=type_option,
-            team_ids=list(team_map.keys()),
-            user_ids=list(user_map.keys()),
-        )
-
-        result: MutableMapping[Union[Team, User], MutableMapping[str, Set[Any]]] = defaultdict(
-            lambda: defaultdict(set)
-        )
-        for _, team in team_map.items():
-            result[team]["settings"] = set()
-        for _, user in user_map.items():
-            result[user]["settings"] = set()
-
-        for notifications_setting in notifications_settings:
-            if notifications_setting.user_id:
-                target_user = user_map[notifications_setting.user_id]
-                result[target_user]["settings"].add(notifications_setting)
-            elif notifications_setting.team_id:
-                target_team = team_map[notifications_setting.team_id]
-                result[target_team]["settings"].add(notifications_setting)
-            else:
-                raise ValueError(
-                    f"NotificationSetting {notifications_setting.id} has neither team_id nor user_id"
-                )
-        return result
-
-    def serialize(
-        self,
-        obj: Union[Team, User],
-        attrs: Mapping[str, Iterable[Any]],
-        user: User,
-        **kwargs: Any,
-    ) -> Mapping[str, Mapping[str, Mapping[int, Mapping[str, str]]]]:
-        """
-        Convert a user or team's NotificationSettings to a python object
-        comprised of primitives. This will backfill all possible notification
-        settings with the appropriate defaults.
-
-        Example: {
-            "workflow": {
-                "project": {
-                    1: {
-                        "email": "always",
-                        "slack": "always"
-                    },
-                    2: {
-                        "email": "subscribe_only",
-                        "slack": "subscribe_only"
-                    }
-                }
-            }
-        }
-
-        :param obj: A user or team.
-        :param attrs: The `obj` target's NotificationSettings
-        :param user: The user who will be viewing the NotificationSettings.
-        :param kwargs: The same `kwargs` as `get_attrs`.
-        :returns A mapping. See example.
-        """
-
-        data: MutableMapping[
-            str, MutableMapping[str, MutableMapping[int, MutableMapping[str, str]]]
-        ] = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
-
-        # Forgive the variable name, I wanted the following lines to be legible.
-        for n in attrs["settings"]:
-            # Override the notification settings.
-            data[n.type_str][n.scope_str][n.scope_identifier][n.provider_str] = n.value_str
-        return data

+ 44 - 5
tests/sentry/api/endpoints/test_team_notification_settings.py

@@ -19,16 +19,55 @@ class TeamNotificationSettingsTestBase(APITestCase):
 class TeamNotificationSettingsGetTest(TeamNotificationSettingsTestBase):
     def test_simple(self):
         _ = self.project  # HACK to force creation.
-        response = self.get_success_response(self.organization.slug, self.team.slug)
+
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.EMAIL,
+            NotificationSettingTypes.ISSUE_ALERTS,
+            NotificationSettingOptionValues.ALWAYS,
+            team_id=self.team.id,
+            project=self.project,
+        )
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.EMAIL,
+            NotificationSettingTypes.DEPLOY,
+            NotificationSettingOptionValues.NEVER,
+            team_id=self.team.id,
+            organization=self.organization,
+        )
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.SLACK,
+            NotificationSettingTypes.WORKFLOW,
+            NotificationSettingOptionValues.DEFAULT,
+            team_id=self.team.id,
+            project=self.project,
+        )
+
+        response = self.get_success_response(
+            self.organization.slug, self.team.slug, v2="serializer"
+        )
 
         # Spot check.
-        assert response.data["alerts"]["project"][self.project.id]["email"] == "default"
-        assert response.data["deploy"]["organization"][self.organization.id]["email"] == "default"
-        assert response.data["workflow"]["project"][self.project.id]["slack"] == "default"
+        assert response.data["alerts"]["project"][self.project.id]["email"] == "always"
+        assert response.data["deploy"]["organization"][self.organization.id]["email"] == "never"
+        assert not response.data["workflow"]
 
     def test_type_querystring(self):
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.EMAIL,
+            NotificationSettingTypes.ISSUE_ALERTS,
+            NotificationSettingOptionValues.ALWAYS,
+            team_id=self.team.id,
+        )
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.SLACK,
+            NotificationSettingTypes.WORKFLOW,
+            NotificationSettingOptionValues.ALWAYS,
+            team_id=self.team.id,
+        )
         response = self.get_success_response(
-            self.organization.slug, self.team.slug, qs_params={"type": "workflow"}
+            self.organization.slug,
+            self.team.slug,
+            qs_params={"type": "workflow", "v2": "serializer"},
         )
 
         assert "alerts" not in response.data

+ 0 - 143
tests/sentry/api/endpoints/test_team_notification_settings2.py

@@ -1,143 +0,0 @@
-from rest_framework import status
-
-from sentry.models import NotificationSetting
-from sentry.notifications.types import NotificationSettingOptionValues, NotificationSettingTypes
-from sentry.testutils import APITestCase
-from sentry.testutils.silo import region_silo_test
-from sentry.types.integrations import ExternalProviders
-
-
-class TeamNotificationSettingsTestBase(APITestCase):
-    endpoint = "sentry-api-0-team-notification-settings"
-
-    def setUp(self):
-        super().setUp()
-        self.login_as(self.user)
-
-
-@region_silo_test()
-class TeamNotificationSettingsGetTest(TeamNotificationSettingsTestBase):
-    def test_simple(self):
-        _ = self.project  # HACK to force creation.
-
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.ISSUE_ALERTS,
-            NotificationSettingOptionValues.ALWAYS,
-            team_id=self.team.id,
-            project=self.project,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.DEPLOY,
-            NotificationSettingOptionValues.NEVER,
-            team_id=self.team.id,
-            organization=self.organization,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.WORKFLOW,
-            NotificationSettingOptionValues.DEFAULT,
-            team_id=self.team.id,
-            project=self.project,
-        )
-
-        response = self.get_success_response(
-            self.organization.slug, self.team.slug, v2="serializer"
-        )
-
-        # Spot check.
-        assert response.data["alerts"]["project"][self.project.id]["email"] == "always"
-        assert response.data["deploy"]["organization"][self.organization.id]["email"] == "never"
-        assert not response.data["workflow"]
-
-    def test_type_querystring(self):
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.ISSUE_ALERTS,
-            NotificationSettingOptionValues.ALWAYS,
-            team_id=self.team.id,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.WORKFLOW,
-            NotificationSettingOptionValues.ALWAYS,
-            team_id=self.team.id,
-        )
-        response = self.get_success_response(
-            self.organization.slug,
-            self.team.slug,
-            qs_params={"type": "workflow", "v2": "serializer"},
-        )
-
-        assert "alerts" not in response.data
-        assert "workflow" in response.data
-
-    def test_invalid_querystring(self):
-        self.get_error_response(
-            self.organization.slug,
-            self.team.slug,
-            qs_params={"type": "invalid"},
-            status_code=status.HTTP_400_BAD_REQUEST,
-        )
-
-    def test_invalid_team_slug(self):
-        self.get_error_response(
-            self.organization.slug, "invalid", status_code=status.HTTP_404_NOT_FOUND
-        )
-
-    def test_wrong_team_slug(self):
-        other_org = self.create_organization()
-        other_team = self.create_team(organization=other_org, name="Tesla Motors")
-
-        self.get_error_response(
-            other_org.slug, other_team.slug, status_code=status.HTTP_403_FORBIDDEN
-        )
-
-
-@region_silo_test()
-class TeamNotificationSettingsTest(TeamNotificationSettingsTestBase):
-    method = "put"
-
-    def test_simple(self):
-        assert (
-            NotificationSetting.objects.get_settings(
-                provider=ExternalProviders.SLACK,
-                type=NotificationSettingTypes.ISSUE_ALERTS,
-                team_id=self.team.id,
-                project=self.project,
-            )
-            == NotificationSettingOptionValues.DEFAULT
-        )
-
-        self.get_success_response(
-            self.organization.slug,
-            self.team.slug,
-            alerts={"project": {self.project.id: {"email": "always", "slack": "always"}}},
-            status_code=status.HTTP_204_NO_CONTENT,
-        )
-
-        assert (
-            NotificationSetting.objects.get_settings(
-                provider=ExternalProviders.SLACK,
-                type=NotificationSettingTypes.ISSUE_ALERTS,
-                team_id=self.team.id,
-                project=self.project,
-            )
-            == NotificationSettingOptionValues.ALWAYS
-        )
-
-    def test_empty_payload(self):
-        self.get_error_response(
-            self.organization.slug,
-            self.team.slug,
-            status_code=status.HTTP_400_BAD_REQUEST,
-        )
-
-    def test_invalid_payload(self):
-        self.get_error_response(
-            self.organization.slug,
-            self.team.slug,
-            invalid=1,
-            status_code=status.HTTP_400_BAD_REQUEST,
-        )

+ 18 - 25
tests/sentry/api/endpoints/test_user_notification_settings.py

@@ -15,7 +15,7 @@ class UserNotificationSettingsTestBase(APITestCase):
         self.login_as(self.user)
 
 
-@control_silo_test()
+@control_silo_test(stable=True)
 class UserNotificationSettingsGetTest(UserNotificationSettingsTestBase):
     def test_simple(self):
         NotificationSetting.objects.update_settings(
@@ -58,13 +58,24 @@ class UserNotificationSettingsGetTest(UserNotificationSettingsTestBase):
 
         response = self.get_success_response("me")
 
-        # Spot check.
-        assert response.data["alerts"]["user"][self.user.id]["email"] == "always"
-        assert response.data["deploy"]["organization"][self.organization.id]["email"] == "default"
-        assert response.data["deploy"]["organization"][self.organization.id]["slack"] == "default"
-        assert response.data["workflow"]["user"][self.user.id]["slack"] == "subscribe_only"
+        # Defaults are handled on the FE
+        assert response.data["preferences"] == {}
 
     def test_type_querystring(self):
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.EMAIL,
+            NotificationSettingTypes.ISSUE_ALERTS,
+            NotificationSettingOptionValues.ALWAYS,
+            user_id=self.user.id,
+            project=self.project,
+        )
+        NotificationSetting.objects.update_settings(
+            ExternalProviders.SLACK,
+            NotificationSettingTypes.WORKFLOW,
+            NotificationSettingOptionValues.ALWAYS,
+            user_id=self.user.id,
+            project=self.project,
+        )
         response = self.get_success_response("me", qs_params={"type": "workflow"})
 
         assert "alerts" not in response.data
@@ -83,26 +94,8 @@ class UserNotificationSettingsGetTest(UserNotificationSettingsTestBase):
 
         self.get_error_response(other_user.id, status_code=status.HTTP_403_FORBIDDEN)
 
-    def test_invalid_notification_setting(self):
-        other_organization = self.create_organization(name="Rowdy Tiger", owner=None)
-        other_project = self.create_project(
-            organization=other_organization, teams=[], name="Bengal"
-        )
-
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.WORKFLOW,
-            NotificationSettingOptionValues.SUBSCRIBE_ONLY,
-            user_id=self.user.id,
-            project=other_project,
-        )
-
-        response = self.get_success_response("me")
-
-        assert other_project.id not in response.data["workflow"]["project"]
-
 
-@control_silo_test()
+@control_silo_test(stable=True)
 class UserNotificationSettingsUpdateTest(UserNotificationSettingsTestBase):
     method = "put"
 

+ 0 - 146
tests/sentry/api/endpoints/test_user_notification_settings2.py

@@ -1,146 +0,0 @@
-from rest_framework import status
-
-from sentry.models import NotificationSetting
-from sentry.notifications.types import NotificationSettingOptionValues, NotificationSettingTypes
-from sentry.testutils import APITestCase
-from sentry.testutils.silo import control_silo_test
-from sentry.types.integrations import ExternalProviders
-
-
-class UserNotificationSettingsTestBase(APITestCase):
-    endpoint = "sentry-api-0-user-notification-settings"
-
-    def setUp(self):
-        super().setUp()
-        self.login_as(self.user)
-
-
-@control_silo_test(stable=True)
-class UserNotificationSettingsGetTest(UserNotificationSettingsTestBase):
-    def test_simple(self):
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.ISSUE_ALERTS,
-            NotificationSettingOptionValues.NEVER,
-            user_id=self.user.id,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.DEPLOY,
-            NotificationSettingOptionValues.NEVER,
-            user_id=self.user.id,
-            organization=self.organization,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.DEPLOY,
-            NotificationSettingOptionValues.ALWAYS,
-            user_id=self.user.id,
-            organization=self.organization,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.WORKFLOW,
-            NotificationSettingOptionValues.SUBSCRIBE_ONLY,
-            user_id=self.user.id,
-        )
-
-        response = self.get_success_response("me", v2="serializer")
-
-        # Spot check.
-        assert response.data["alerts"]["user"][self.user.id]["email"] == "never"
-        assert response.data["deploy"]["organization"][self.organization.id]["email"] == "never"
-        assert response.data["deploy"]["organization"][self.organization.id]["slack"] == "always"
-        assert response.data["workflow"]["user"][self.user.id]["slack"] == "subscribe_only"
-
-    def test_notification_settings_empty(self):
-        _ = self.organization  # HACK to force creation.
-
-        response = self.get_success_response("me", v2="serializer")
-
-        # Defaults are handled on the FE
-        assert response.data["preferences"] == {}
-
-    def test_type_querystring(self):
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.EMAIL,
-            NotificationSettingTypes.ISSUE_ALERTS,
-            NotificationSettingOptionValues.ALWAYS,
-            user_id=self.user.id,
-            project=self.project,
-        )
-        NotificationSetting.objects.update_settings(
-            ExternalProviders.SLACK,
-            NotificationSettingTypes.WORKFLOW,
-            NotificationSettingOptionValues.ALWAYS,
-            user_id=self.user.id,
-            project=self.project,
-        )
-        response = self.get_success_response(
-            "me", qs_params={"type": "workflow", "v2": "serializer"}
-        )
-
-        assert "alerts" not in response.data
-        assert "workflow" in response.data
-
-    def test_invalid_querystring(self):
-        self.get_error_response(
-            "me", qs_params={"type": "invalid"}, status_code=status.HTTP_400_BAD_REQUEST
-        )
-
-    def test_invalid_user_id(self):
-        self.get_error_response("invalid", status_code=status.HTTP_404_NOT_FOUND)
-
-    def test_wrong_user_id(self):
-        other_user = self.create_user("bizbaz@example.com")
-
-        self.get_error_response(other_user.id, status_code=status.HTTP_403_FORBIDDEN)
-
-
-@control_silo_test(stable=True)
-class UserNotificationSettingsUpdateTest(UserNotificationSettingsTestBase):
-    method = "put"
-
-    def test_simple(self):
-        _ = self.project  # HACK to force creation.
-
-        assert (
-            NotificationSetting.objects.get_settings(
-                provider=ExternalProviders.SLACK,
-                type=NotificationSettingTypes.DEPLOY,
-                user_id=self.user.id,
-            )
-            == NotificationSettingOptionValues.DEFAULT
-        )
-
-        self.get_success_response(
-            "me",
-            deploy={"user": {"me": {"email": "always", "slack": "always"}}},
-            status_code=status.HTTP_204_NO_CONTENT,
-        )
-
-        assert (
-            NotificationSetting.objects.get_settings(
-                provider=ExternalProviders.SLACK,
-                type=NotificationSettingTypes.DEPLOY,
-                user_id=self.user.id,
-            )
-            == NotificationSettingOptionValues.ALWAYS
-        )
-
-    def test_empty_payload(self):
-        self.get_error_response("me", status_code=status.HTTP_400_BAD_REQUEST)
-
-    def test_invalid_payload(self):
-        self.get_error_response("me", invalid=1, status_code=status.HTTP_400_BAD_REQUEST)
-
-    def test_malformed_payload(self):
-        self.get_error_response("me", alerts=[1, 2], status_code=status.HTTP_400_BAD_REQUEST)
-
-    def test_wrong_user_id(self):
-        user2 = self.create_user()
-        self.get_error_response(
-            "me",
-            deploy={"user": {user2.id: {"email": "always", "slack": "always"}}},
-            status_code=status.HTTP_400_BAD_REQUEST,
-        )