Add /submessage endpoint.

This commit is contained in:
Steve Howell
2018-02-12 04:53:36 -05:00
committed by Tim Abbott
parent 33d753d174
commit de47eeb6f1
6 changed files with 191 additions and 1 deletions

View File

@@ -64,7 +64,7 @@ from zerver.lib.topic_mutes import (
from zerver.lib.users import bulk_get_users, check_full_name, user_ids_to_users
from zerver.lib.user_groups import create_user_group, access_user_group_by_id
from zerver.models import Realm, RealmEmoji, Stream, UserProfile, UserActivity, \
RealmDomain, Service, \
RealmDomain, Service, SubMessage, \
Subscription, Recipient, Message, Attachment, UserMessage, RealmAuditLog, \
UserHotspot, MultiuseInvite, ScheduledMessage, \
Client, DefaultStream, DefaultStreamGroup, UserPresence, PushDeviceToken, \
@@ -1424,6 +1424,32 @@ def bulk_insert_ums(ums: List[UserMessageLite]) -> None:
with connection.cursor() as cursor:
cursor.execute(query)
def do_add_submessage(sender_id: int,
message_id: int,
msg_type: str,
content: str,
data: Any,
) -> None:
submessage = SubMessage(
sender_id=sender_id,
message_id=message_id,
msg_type=msg_type,
content=content,
)
submessage.save()
event = dict(
type="submessage",
msg_type=msg_type,
message_id=message_id,
sender_id=sender_id,
data=data,
)
ums = UserMessage.objects.filter(message_id=message_id)
target_user_ids = [um.user_profile_id for um in ums]
send_event(event, target_user_ids)
def notify_reaction_update(user_profile: UserProfile, message: Message,
reaction: Reaction, op: str) -> None:
user_dict = {'user_id': user_profile.id,

View File

@@ -560,6 +560,9 @@ def apply_event(state: Dict[str, Any],
elif event['type'] == "reaction":
# The client will get the message with the reactions directly
pass
elif event['type'] == "submessage":
# The client will get submessages with their messages
pass
elif event['type'] == 'typing':
# Typing notification events are transient and thus ignored
pass

View File

@@ -33,6 +33,7 @@ from zerver.lib.actions import (
do_add_realm_domain,
do_add_realm_filter,
do_add_streams_to_default_stream_group,
do_add_submessage,
do_change_avatar_fields,
do_change_bot_owner,
do_change_default_all_public_streams,
@@ -867,6 +868,34 @@ class EventsRegisterTest(ZulipTestCase):
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
def test_add_submessage(self) -> None:
schema_checker = self.check_events_dict([
('type', equals('submessage')),
('message_id', check_int),
('sender_id', check_int),
('msg_type', check_string),
('data', check_string),
])
cordelia = self.example_user('cordelia')
stream_name = 'Verona'
message_id = self.send_stream_message(
sender_email=cordelia.email,
stream_name=stream_name,
)
events = self.do_test(
lambda: do_add_submessage(
sender_id=cordelia.id,
message_id=message_id,
msg_type='whatever',
content='"stuff"',
data='stuff',
),
state_change_expected=False,
)
error = schema_checker('events[0]', events[0])
self.assert_on_error(error)
def test_remove_reaction(self) -> None:
schema_checker = self.check_events_dict([
('type', equals('reaction')),

View File

@@ -1,3 +1,5 @@
import mock
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.message import (
@@ -73,3 +75,83 @@ class TestBasics(ZulipTestCase):
rows = msg_rows[0]['submessages']
rows.sort(key=lambda r: r['id'])
self.assertEqual(rows, expected_data)
def test_endpoint_errors(self) -> None:
cordelia = self.example_user('cordelia')
stream_name = 'Verona'
message_id = self.send_stream_message(
sender_email=cordelia.email,
stream_name=stream_name,
)
self.login(cordelia.email)
payload = dict(
message_id=message_id,
msg_type='whatever',
content='not json',
)
result = self.client_post('/json/submessage', payload)
self.assert_json_error(result, 'Invalid json for submessage')
hamlet = self.example_user('hamlet')
bad_message_id = self.send_personal_message(
from_email=hamlet.email,
to_email=hamlet.email,
)
payload = dict(
message_id=bad_message_id,
msg_type='whatever',
content='does not matter',
)
result = self.client_post('/json/submessage', payload)
self.assert_json_error(result, 'Invalid message(s)')
def test_endpoint_success(self) -> None:
cordelia = self.example_user('cordelia')
hamlet = self.example_user('hamlet')
stream_name = 'Verona'
message_id = self.send_stream_message(
sender_email=cordelia.email,
stream_name=stream_name,
)
self.login(cordelia.email)
payload = dict(
message_id=message_id,
msg_type='whatever',
content='{"name": "alice", "salary": 20}'
)
with mock.patch('zerver.lib.actions.send_event') as m:
result = self.client_post('/json/submessage', payload)
self.assert_json_success(result)
expected_data = dict(
message_id=message_id,
data=dict(
name='alice',
salary=20,
),
msg_type='whatever',
sender_id=cordelia.id,
type='submessage',
)
self.assertEqual(m.call_count, 1)
data = m.call_args[0][0]
self.assertEqual(data, expected_data)
users = m.call_args[0][1]
self.assertIn(cordelia.id, users)
self.assertIn(hamlet.id, users)
rows = SubMessage.get_raw_db_rows([message_id])
self.assertEqual(len(rows), 1)
row = rows[0]
expected_data = dict(
id=row['id'],
message_id=message_id,
content='{"name": "alice", "salary": 20}',
msg_type='whatever',
sender_id=cordelia.id,
)
self.assertEqual(row, expected_data)

View File

@@ -0,0 +1,46 @@
import logging
import ujson
from django.http import HttpRequest, HttpResponse
from django.utils.translation import ugettext as _
from django.conf import settings
from zerver.decorator import (
has_request_variables,
REQ,
)
from zerver.lib.actions import do_add_submessage
from zerver.lib.message import access_message
from zerver.lib.validator import check_int
from zerver.lib.response import (
json_error,
json_success
)
from zerver.models import UserProfile
@has_request_variables
def process_submessage(request: HttpRequest,
user_profile: UserProfile,
message_id: int=REQ(validator=check_int),
msg_type: str=REQ(),
content: str=REQ(),
) -> HttpResponse:
message, user_message = access_message(user_profile, message_id)
if not settings.ALLOW_SUB_MESSAGES: # nocoverage
msg = 'Feature not enabled'
return json_error(msg)
try:
data = ujson.loads(content)
except Exception:
return json_error(_("Invalid json for submessage"))
do_add_submessage(
sender_id=user_profile.id,
message_id=message.id,
msg_type=msg_type,
content=content,
data=data,
)
return json_success()

View File

@@ -187,6 +187,10 @@ v1_api_and_json_patterns = [
url(r'users/me/subscriptions/(?P<stream_id>\d+)$', rest_dispatch,
{'PATCH': 'zerver.views.streams.update_subscriptions_property'}),
url(r'^submessage$',
rest_dispatch,
{'POST': 'zerver.views.submessage.process_submessage'}),
# New endpoint for handling reactions.
url(r'^messages/(?P<message_id>[0-9]+)/reactions$',
rest_dispatch,