Skip to content

Commit 2b8fcc2

Browse files
Add fixes to user authentication and send a message to a specific one
1 parent 8f394fc commit 2b8fcc2

File tree

6 files changed

+21
-47
lines changed

6 files changed

+21
-47
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ To authenticate users on Pusher Channels on your application, you can use the au
329329
|:-:|:-:|
330330
|response `Dict` | A dictionary to send as a response to the authentication request.|
331331

332-
For more information see [authenticating users](https://pusher.com/docs/channels/server_api/authenticating-users/).
332+
For more information see:
333+
* [authenticating users](https://pusher.com/docs/channels/server_api/authenticating-users/)
334+
* [auth-signatures](https://pusher.com/docs/channels/library_auth_reference/auth-signatures/)
333335

334336
##### Example
335337

pusher/pusher.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from pusher.util import (
1717
ensure_text,
1818
pusher_url_re,
19-
doc_string)
19+
doc_string, validate_user_id)
2020

2121
from pusher.pusher_client import PusherClient
2222
from pusher.authentication_client import AuthenticationClient
@@ -146,9 +146,11 @@ def trigger(self, channels, event_name, data, socket_id=None):
146146
return self._pusher_client.trigger(
147147
channels, event_name, data, socket_id)
148148

149-
@doc_string(PusherClient.send_to_user.__doc__)
149+
@doc_string(PusherClient.trigger.__doc__)
150150
def send_to_user(self, user_id, event_name, data):
151-
return self._pusher_client.send_to_user(user_id, event_name, data)
151+
validate_user_id(user_id)
152+
user_server_string = "#server-to-user-%s" % user_id
153+
return self._pusher_client.trigger([user_server_string], event_name, data)
152154

153155
@doc_string(PusherClient.trigger_batch.__doc__)
154156
def trigger_batch(self, batch=[], already_encoded=False):

pusher/pusher_client.py

-7
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,6 @@ def trigger(self, channels, event_name, data, socket_id=None):
114114

115115
return Request(self, POST, "/apps/%s/events" % self.app_id, params)
116116

117-
def send_to_user(self, user_id, event_name, data):
118-
"""Send an event to a specific user
119-
"""
120-
validate_user_id(user_id)
121-
user_server_string = "#server-to-user-%s" % user_id
122-
return self.trigger([user_server_string], event_name, data)
123-
124117
@request_method
125118
def trigger_batch(self, batch=[], already_encoded=False):
126119
"""Trigger multiple events with a single HTTP call.

pusher/util.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
import six
1212
import sys
1313
import base64
14+
SERVER_TO_USER_PREFIX = "#server-to-user-"
1415

1516
channel_name_re = re.compile(r'\A[-a-zA-Z0-9_=@,.;]+\Z')
16-
server_to_user_channel_re = re.compile(r'\A#server-to-user[-a-zA-Z0-9_=@,.;]+\Z')
17+
server_to_user_channel_re = re.compile(rf'\A{SERVER_TO_USER_PREFIX}[-a-zA-Z0-9_=@,.;]+\Z')
1718
app_id_re = re.compile(r'\A[0-9]+\Z')
1819
pusher_url_re = re.compile(r'\A(http|https)://(.*):(.*)@(.*)/apps/([0-9]+)\Z')
1920
socket_id_re = re.compile(r'\A\d+\.\d+\Z')
@@ -91,12 +92,10 @@ def validate_channel(channel):
9192
if len(channel) > 200:
9293
raise ValueError("Channel too long: %s" % channel)
9394

94-
if "server-to-user" in channel:
95+
if channel.startswith(SERVER_TO_USER_PREFIX):
9596
if not server_to_user_channel_re.match(channel):
9697
raise ValueError("Invalid server to user Channel: %s" % channel)
97-
return channel
98-
99-
if not channel_name_re.match(channel):
98+
elif not channel_name_re.match(channel):
10099
raise ValueError("Invalid Channel: %s" % channel)
101100

102101
return channel
@@ -116,6 +115,7 @@ def validate_user_data(user_data: dict):
116115
raise ValueError('user_data is null')
117116
if user_data.get('id') is None:
118117
raise ValueError('user_data has no id field')
118+
validate_user_id(user_data.get('id'))
119119

120120

121121
def join_attributes(attributes):

pusher_tests/test_pusher_client.py

-22
Original file line numberDiff line numberDiff line change
@@ -360,28 +360,6 @@ def test_terminate_user_connection_fail_case_invalid_user_id(self):
360360
with self.assertRaises(ValueError):
361361
self.pusher_client.terminate_user_connections("")
362362

363-
def test_send_to_user_success_case(self):
364-
json_dumped = u'{"message": "hello worlds"}'
365-
request_params = [u'#server-to-user-123'], u'some_event', {u'message': u'hello worlds'}
366-
367-
with mock.patch('json.dumps', return_value=json_dumped):
368-
with mock.patch(
369-
'pusher.pusher_client.PusherClient.trigger',
370-
return_value=self.pusher_client.trigger.make_request(*request_params)
371-
) as mock_trigger:
372-
request = self.pusher_client.send_to_user(
373-
u'123', u'some_event', {u'message': u'hello worlds'}
374-
)
375-
376-
expected_params = {
377-
u'channels': [u'#server-to-user-123'],
378-
u'data': json_dumped,
379-
u'name': u'some_event'
380-
}
381-
382-
self.assertEqual(request.params, expected_params)
383-
mock_trigger.assert_called_with(*request_params)
384-
385363

386364
if __name__ == '__main__':
387365
unittest.main()

pusher_tests/test_util.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ def test_validate_user_id(self):
1616
pusher.util.validate_user_id(user_id)
1717

1818
def test_validate_channel(self):
19-
valid_channels = ["123", "xyz", "xyz123", "xyz_123", "xyz-123", "Channel@123", "channel_xyz", "channel-xyz",
20-
"channel,456", "channel;asd", "[email protected],987;654"]
19+
valid_channels = ["123", "xyz", "xyz123", "xyz_123", "xyz-123", "Channel@123", "channel_xyz", "channel-xyz", "channel,456", "channel;asd", "[email protected],987;654"]
2120

22-
invalid_channels = ["#123", "x" * 201, "abc%&*"]
21+
invalid_channels = ["#123", "x" * 201, "abc%&*", "#server-to-user1234", "#server-to-users"]
2322

2423
for channel in valid_channels:
2524
self.assertEqual(channel, pusher.util.validate_channel(channel))
@@ -29,14 +28,14 @@ def test_validate_channel(self):
2928
pusher.util.validate_channel(invalid_channel)
3029

3130
def test_validate_server_to_user_channel(self):
31+
self.assertEqual("#server-to-user-123", pusher.util.validate_channel("#server-to-user-123"))
32+
self.assertEqual("#server-to-user-user123", pusher.util.validate_channel("#server-to-user-user123"))
33+
self.assertEqual("#server-to-user-ID-123", pusher.util.validate_channel("#server-to-user-ID-123"))
3234

33-
valid_server_to_user_channel = "#server-to-user-123"
34-
35-
invalid_server_to_user_channel = "#server-to-useR-123"
36-
37-
self.assertEqual(valid_server_to_user_channel, pusher.util.validate_channel(valid_server_to_user_channel))
3835
with self.assertRaises(ValueError):
39-
pusher.util.validate_channel(invalid_server_to_user_channel)
36+
pusher.util.validate_channel("#server-to-useR-123")
37+
pusher.util.validate_channel("#server-to-user1234")
38+
pusher.util.validate_channel("#server-to-users")
4039

4140

4241
if __name__ == '__main__':

0 commit comments

Comments
 (0)