notification: send a notification to several users (#60643)
This commit is contained in:
parent
93d54bf08f
commit
0be1356882
|
@ -14,11 +14,15 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import transaction
|
||||
from django.utils.encoding import force_text
|
||||
from rest_framework import authentication, permissions, serializers, status
|
||||
from rest_framework.generics import GenericAPIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
from combo.profile.utils import get_user_from_name_id
|
||||
|
||||
from .models import Notification
|
||||
|
||||
|
||||
|
@ -31,6 +35,27 @@ class NotificationSerializer(serializers.Serializer):
|
|||
start_timestamp = serializers.DateTimeField(required=False, allow_null=True)
|
||||
end_timestamp = serializers.DateTimeField(required=False, allow_null=True)
|
||||
duration = serializers.IntegerField(required=False, allow_null=True, min_value=0)
|
||||
name_ids = serializers.ListField(
|
||||
required=False, child=serializers.CharField(required=True, max_length=150)
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
super().validate(attrs)
|
||||
users = []
|
||||
founded = []
|
||||
missing = []
|
||||
for uuid in attrs.get('name_ids') or []:
|
||||
try:
|
||||
user = get_user_from_name_id(uuid, raise_on_missing=True)
|
||||
except User.DoesNotExist:
|
||||
missing.append(uuid)
|
||||
else:
|
||||
users.append(user)
|
||||
founded.append(uuid)
|
||||
attrs['users'] = users
|
||||
attrs['founded_uuids'] = founded
|
||||
attrs['missing_uuids'] = missing
|
||||
return attrs
|
||||
|
||||
|
||||
class Add(GenericAPIView):
|
||||
|
@ -42,25 +67,41 @@ class Add(GenericAPIView):
|
|||
if not serializer.is_valid():
|
||||
response = {'err': 1, 'err_desc': serializer.errors}
|
||||
return Response(response, status.HTTP_400_BAD_REQUEST)
|
||||
data = serializer.validated_data
|
||||
payload = serializer.validated_data
|
||||
notification_ids = []
|
||||
try:
|
||||
notification = Notification.notify(
|
||||
user=request.user,
|
||||
summary=data['summary'],
|
||||
id=data.get('id'),
|
||||
body=data.get('body'),
|
||||
url=data.get('url'),
|
||||
origin=data.get('origin'),
|
||||
start_timestamp=data.get('start_timestamp'),
|
||||
end_timestamp=data.get('end_timestamp'),
|
||||
duration=data.get('duration'),
|
||||
)
|
||||
with transaction.atomic():
|
||||
for user in payload.get('users') or [request.user]:
|
||||
notification = Notification.notify(
|
||||
user=user,
|
||||
summary=payload['summary'],
|
||||
id=payload.get('id'),
|
||||
body=payload.get('body'),
|
||||
url=payload.get('url'),
|
||||
origin=payload.get('origin'),
|
||||
start_timestamp=payload.get('start_timestamp'),
|
||||
end_timestamp=payload.get('end_timestamp'),
|
||||
duration=payload.get('duration'),
|
||||
)
|
||||
notification_ids.append(notification.public_id)
|
||||
except ValueError as e:
|
||||
response = {'err': 1, 'err_desc': {'id': [force_text(e)]}}
|
||||
return Response(response, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
data = {}
|
||||
if not payload.get('name_ids'):
|
||||
data = {'id': notification_ids.pop()}
|
||||
else:
|
||||
response = {'err': 0, 'data': {'id': notification.public_id}}
|
||||
return Response(response)
|
||||
data = {
|
||||
'nb_notify': len(notification_ids),
|
||||
'notified': payload.get('founded_uuids'),
|
||||
'unnotified': payload.get('missing_uuids'),
|
||||
}
|
||||
if payload.get('id'):
|
||||
data['id'] = payload.get('id')
|
||||
else:
|
||||
data['ids'] = notification_ids
|
||||
return Response({'err': 0, 'data': data})
|
||||
|
||||
|
||||
add = Add.as_view()
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.test.client import RequestFactory
|
|||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.timezone import now
|
||||
from mellon.models import UserSAMLIdentifier
|
||||
|
||||
from combo.apps.lingo.models import ActiveItems, PaymentBackend, Regie
|
||||
from combo.apps.notifications.models import Notification, NotificationsCell
|
||||
|
@ -518,3 +519,72 @@ def test_notification_never_expire(app, freezer, rf, john_doe):
|
|||
assert Notification.objects.visible(john_doe).count() == 1
|
||||
assert 'notibar' in content
|
||||
assert 'notifoo' not in content
|
||||
|
||||
|
||||
def test_notification_ws_create_many(john_doe, jane_doe):
|
||||
UserSAMLIdentifier.objects.create(user=john_doe, name_id='00a')
|
||||
UserSAMLIdentifier.objects.create(user=jane_doe, name_id='00b')
|
||||
login(john_doe)
|
||||
|
||||
data = {'summary': 'foo', 'name_ids': ['00a', '00b']}
|
||||
resp = client.post(reverse('api-notification-add'), json.dumps(data), content_type='application/json')
|
||||
assert resp.status_code == 200
|
||||
assert len(resp.json()['data']['ids']) == 2
|
||||
assert Notification.objects.count() == 2
|
||||
assert Notification.objects.get(user=john_doe, id=resp.json()['data']['ids'][0]).summary == 'foo'
|
||||
assert Notification.objects.get(user=jane_doe, id=resp.json()['data']['ids'][1]).summary == 'foo'
|
||||
resp.json()['data']['ids'] = ['xx', 'yy']
|
||||
assert resp.json() == {
|
||||
'err': 0,
|
||||
'data': {'nb_notify': 2, 'notified': ['00a', '00b'], 'unnotified': [], 'ids': ['xx', 'yy']},
|
||||
}
|
||||
|
||||
# wrong username
|
||||
data = {'summary': 'bar', 'name_ids': ['00a', 'unknown']}
|
||||
resp = client.post(reverse('api-notification-add'), json.dumps(data), content_type='application/json')
|
||||
assert resp.status_code == 200
|
||||
assert len(resp.json()['data']['ids']) == 1
|
||||
assert Notification.objects.count() == 3
|
||||
assert Notification.objects.get(user=john_doe, id=resp.json()['data']['ids'][0]).summary == 'bar'
|
||||
resp.json()['data']['ids'] = ['xx']
|
||||
assert resp.json() == {
|
||||
'err': 0,
|
||||
'data': {'nb_notify': 1, 'notified': ['00a'], 'unnotified': ['unknown'], 'ids': ['xx']},
|
||||
}
|
||||
|
||||
|
||||
def test_notification_ws_update_many(john_doe, jane_doe):
|
||||
UserSAMLIdentifier.objects.create(user=john_doe, name_id='00a')
|
||||
UserSAMLIdentifier.objects.create(user=jane_doe, name_id='00b')
|
||||
login(john_doe)
|
||||
|
||||
data = {
|
||||
'summary': 'foo',
|
||||
'name_ids': ['00a', '00b'],
|
||||
'id': 'test:42',
|
||||
}
|
||||
resp = client.post(reverse('api-notification-add'), json.dumps(data), content_type='application/json')
|
||||
assert resp.status_code == 200
|
||||
result = resp.json()
|
||||
assert resp.json() == {
|
||||
'err': 0,
|
||||
'data': {'nb_notify': 2, 'notified': ['00a', '00b'], 'unnotified': [], 'id': 'test:42'},
|
||||
}
|
||||
assert Notification.objects.count() == 2
|
||||
assert Notification.objects.get(user=john_doe, external_id='test:42').summary == 'foo'
|
||||
assert Notification.objects.get(user=jane_doe, external_id='test:42').summary == 'foo'
|
||||
|
||||
data['summary'] = 'bar'
|
||||
resp = client.post(reverse('api-notification-add'), json.dumps(data), content_type='application/json')
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == {
|
||||
'err': 0,
|
||||
'data': {'nb_notify': 2, 'notified': ['00a', '00b'], 'unnotified': [], 'id': 'test:42'},
|
||||
}
|
||||
result = resp.json()
|
||||
assert result['err'] == 0
|
||||
assert result['data']['nb_notify'] == 2
|
||||
assert result['data']['id'] == 'test:42'
|
||||
assert Notification.objects.count() == 2
|
||||
assert Notification.objects.get(user=john_doe, external_id='test:42').summary == 'bar'
|
||||
assert Notification.objects.get(user=jane_doe, external_id='test:42').summary == 'bar'
|
||||
|
|
Loading…
Reference in New Issue