Skip to content

Commit cae9266

Browse files
authored
fix(taskworker) Fix more pickle parameter usage in send_async_notification (#90779)
AnonymousUser() can be included in the parameter for notifications and needs special cased serialization logic. Fixes #90763
1 parent 12e47d4 commit cae9266

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/sentry/notifications/utils/tasks.py

+20
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import TYPE_CHECKING, Any
66

77
from django.apps import apps
8+
from django.contrib.auth.models import AnonymousUser
89
from django.utils.functional import SimpleLazyObject
910

1011
from sentry.db.models import Model
@@ -19,6 +20,7 @@
1920
from sentry.notifications.notifications.base import BaseNotification
2021

2122

23+
ANONYMOUS_USER_KEY = "anonymoususer"
2224
LAZY_OBJECT_KEY = "lazyobjectrpcuser"
2325
MODEL_KEY = "model"
2426

@@ -50,6 +52,14 @@ def serialize_model(arg: Model, key: str | None = None) -> dict[str, Any]:
5052
}
5153

5254

55+
def serialize_anonymous_user(arg: AnonymousUser, key: str | None = None) -> dict[str, Any]:
56+
return {
57+
"type": ANONYMOUS_USER_KEY,
58+
"data": {},
59+
"key": key,
60+
}
61+
62+
5363
@region_silo_function
5464
def async_send_notification(
5565
NotificationClass: type[BaseNotification], *args: Any, **kwargs: Any
@@ -70,6 +80,8 @@ def async_send_notification(
7080
task_args.append(serialize_model(arg))
7181
elif isinstance(arg, SimpleLazyObject):
7282
task_args.append(serialize_lazy_object_user(arg))
83+
elif isinstance(arg, AnonymousUser):
84+
task_args.append(serialize_anonymous_user(arg))
7385
# maybe we need an explicit check if it's a primitive?
7486
else:
7587
task_args.append({"type": "other", "value": arg, "key": None})
@@ -78,6 +90,8 @@ def async_send_notification(
7890
task_args.append(serialize_model(val, key))
7991
elif isinstance(val, SimpleLazyObject):
8092
task_args.append(serialize_lazy_object_user(val, key))
93+
elif isinstance(val, AnonymousUser):
94+
task_args.append(serialize_anonymous_user(val, key))
8195
# maybe we need an explicit check if it's a primitive?
8296
else:
8397
task_args.append({"type": "other", "value": val, "key": key})
@@ -113,6 +127,12 @@ def _send_notification(notification_class_name: str, arg_list: Iterable[Mapping[
113127
output_kwargs[arg["key"]] = user
114128
else:
115129
output_args.append(user)
130+
elif arg["type"] == ANONYMOUS_USER_KEY:
131+
anon_user = AnonymousUser()
132+
if arg["key"]:
133+
output_kwargs[arg["key"]] = anon_user
134+
else:
135+
output_args.append(anon_user)
116136
elif arg["key"]:
117137
output_kwargs[arg["key"]] = arg["value"]
118138
else:

tests/sentry/notifications/utils/test_tasks.py

+20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from unittest.mock import patch
22

33
import pytest
4+
from django.contrib.auth.models import AnonymousUser
45

56
from sentry.notifications.class_manager import NotificationClassNotSetException, manager, register
67
from sentry.notifications.utils.tasks import _send_notification, async_send_notification
@@ -63,6 +64,25 @@ def test_call_task_with_kwargs(self, mock_delay):
6364
],
6465
)
6566

67+
@patch("sentry.notifications.utils.tasks._send_notification.delay")
68+
def test_call_task_with_anonymous_user(self, mock_delay):
69+
register()(AnotherDummyNotification)
70+
async_send_notification(
71+
AnotherDummyNotification, "some_value", user=AnonymousUser(), key="value"
72+
)
73+
mock_delay.assert_called_with(
74+
"AnotherDummyNotification",
75+
[
76+
{"type": "other", "value": "some_value", "key": None},
77+
{
78+
"type": "anonymoususer",
79+
"data": {},
80+
"key": "user",
81+
},
82+
{"type": "other", "value": "value", "key": "key"},
83+
],
84+
)
85+
6686
@patch(
6787
"sentry.testutils.helpers.notifications.AnotherDummyNotification",
6888
)

0 commit comments

Comments
 (0)