Skip to content

Commit 57360f2

Browse files
Sebastian Molendapubnub-release-bot
andauthored
Handle exception on history unencrypted message (#175)
* Handle exception on history unencrypted message * PubNub SDK v7.3.2 release. --------- Co-authored-by: PubNub Release Bot <120067856+pubnub-release-bot@users.noreply.github.com>
1 parent 5164d88 commit 57360f2

File tree

10 files changed

+297
-16
lines changed

10 files changed

+297
-16
lines changed

.pubnub.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: python
2-
version: 7.3.1
2+
version: 7.3.2
33
schema: 1
44
scm: github.com/pubnub/python
55
sdks:
@@ -18,7 +18,7 @@ sdks:
1818
distributions:
1919
- distribution-type: library
2020
distribution-repository: package
21-
package-name: pubnub-7.3.1
21+
package-name: pubnub-7.3.2
2222
location: https://pypi.org/project/pubnub/
2323
supported-platforms:
2424
supported-operating-systems:
@@ -97,8 +97,8 @@ sdks:
9797
-
9898
distribution-type: library
9999
distribution-repository: git release
100-
package-name: pubnub-7.3.1
101-
location: https://github.com/pubnub/python/releases/download/v7.3.1/pubnub-7.3.1.tar.gz
100+
package-name: pubnub-7.3.2
101+
location: https://github.com/pubnub/python/releases/download/v7.3.2/pubnub-7.3.2.tar.gz
102102
supported-platforms:
103103
supported-operating-systems:
104104
Linux:
@@ -169,6 +169,11 @@ sdks:
169169
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
170170
is-required: Required
171171
changelog:
172+
- date: 2023-11-27
173+
version: v7.3.2
174+
changes:
175+
- type: bug
176+
text: "Gracefully handle decrypting an unencrypted method. If a decryption error occurs when trying to decrypt plain text, the plain text message will be returned and an error field will be set in the response. This works for both history and subscription messages."
172177
- date: 2023-10-30
173178
version: v7.3.1
174179
changes:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v7.3.2
2+
November 27 2023
3+
4+
#### Fixed
5+
- Gracefully handle decrypting an unencrypted method. If a decryption error occurs when trying to decrypt plain text, the plain text message will be returned and an error field will be set in the response. This works for both history and subscription messages.
6+
17
## v7.3.1
28
October 30 2023
39

pubnub/models/consumer/history.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import binascii
2+
3+
14
class PNHistoryResult(object):
25
def __init__(self, messages, start_timetoken, end_timetoken):
36
self.messages = messages
@@ -44,12 +47,16 @@ def __init__(self, entry, crypto, timetoken=None, meta=None):
4447
self.meta = meta
4548
self.entry = entry
4649
self.crypto = crypto
50+
self.error = None
4751

4852
def __str__(self):
4953
return "History item with tt: %s and content: %s" % (self.timetoken, self.entry)
5054

5155
def decrypt(self, cipher_key):
52-
self.entry = self.crypto.decrypt(cipher_key, self.entry)
56+
try:
57+
self.entry = self.crypto.decrypt(cipher_key, self.entry)
58+
except binascii.Error as e:
59+
self.error = e
5360

5461

5562
class PNFetchMessagesResult(object):

pubnub/models/consumer/pubsub.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
class PNMessageResult(object):
5-
def __init__(self, message, subscription, channel, timetoken, user_metadata=None, publisher=None):
5+
def __init__(self, message, subscription, channel, timetoken, user_metadata=None, publisher=None, error=None):
66

77
if subscription is not None:
88
assert isinstance(subscription, str)
@@ -29,6 +29,7 @@ def __init__(self, message, subscription, channel, timetoken, user_metadata=None
2929
self.timetoken = timetoken
3030
self.user_metadata = user_metadata
3131
self.publisher = publisher
32+
self.error = error
3233

3334

3435
class PNSignalMessageResult(PNMessageResult):

pubnub/pubnub_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585

8686
class PubNubCore:
8787
"""A base class for PubNub Python API implementations"""
88-
SDK_VERSION = "7.3.1"
88+
SDK_VERSION = "7.3.2"
8989
SDK_NAME = "PubNub-Python"
9090

9191
TIMESTAMP_DIVIDER = 1000

pubnub/workers.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,23 @@ def _get_url_for_file_event_message(self, channel, extracted_message):
5252

5353
def _process_message(self, message_input):
5454
if self._pubnub.config.cipher_key is None:
55-
return message_input
55+
return message_input, None
5656
else:
5757
try:
5858
return self._pubnub.config.crypto.decrypt(
5959
self._pubnub.config.cipher_key,
6060
message_input
61-
)
61+
), None
6262
except Exception as exception:
6363
logger.warning("could not decrypt message: \"%s\", due to error %s" % (message_input, str(exception)))
64+
6465
pn_status = PNStatus()
6566
pn_status.category = PNStatusCategory.PNDecryptionErrorCategory
6667
pn_status.error_data = PNErrorData(str(exception), exception)
6768
pn_status.error = True
6869
pn_status.operation = PNOperationType.PNSubscribeOperation
6970
self._listener_manager.announce_status(pn_status)
70-
return message_input
71+
return message_input, exception
7172

7273
def _process_incoming_payload(self, message):
7374
assert isinstance(message, SubscribeMessage)
@@ -125,7 +126,7 @@ def _process_incoming_payload(self, message):
125126
)
126127
self._listener_manager.announce_membership(membership_result)
127128
elif message.type == SubscribeMessageWorker.TYPE_FILE_MESSAGE:
128-
extracted_message = self._process_message(message.payload)
129+
extracted_message, _ = self._process_message(message.payload)
129130
download_url = self._get_url_for_file_event_message(channel, extracted_message)
130131

131132
pn_file_result = PNFileMessageResult(
@@ -142,7 +143,7 @@ def _process_incoming_payload(self, message):
142143
self._listener_manager.announce_file_message(pn_file_result)
143144

144145
else:
145-
extracted_message = self._process_message(message.payload)
146+
extracted_message, error = self._process_message(message.payload)
146147
publisher = message.issuing_client_id
147148

148149
if extracted_message is None:
@@ -172,6 +173,7 @@ def _process_incoming_payload(self, message):
172173
channel=channel,
173174
subscription=subscription_match,
174175
timetoken=publish_meta_data.publish_timetoken,
175-
publisher=publisher
176+
publisher=publisher,
177+
error=error
176178
)
177179
self._listener_manager.announce_message(pn_message_result)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='pubnub',
5-
version='7.3.1',
5+
version='7.3.2',
66
description='PubNub Real-time push service in the cloud',
77
author='PubNub',
88
author_email='support@pubnub.com',
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
{
2+
"version": 1,
3+
"interactions": [
4+
{
5+
"request": {
6+
"method": "DELETE",
7+
"uri": "https://ps.pndsn.com/v3/history/sub-key/{PN_KEY_SUBSCRIBE}/channel/test_unencrypted",
8+
"body": null,
9+
"headers": {
10+
"User-Agent": [
11+
"PubNub-Python/7.3.0"
12+
],
13+
"Accept-Encoding": [
14+
"gzip, deflate"
15+
],
16+
"Accept": [
17+
"*/*"
18+
],
19+
"Connection": [
20+
"keep-alive"
21+
],
22+
"Content-Length": [
23+
"0"
24+
]
25+
}
26+
},
27+
"response": {
28+
"status": {
29+
"code": 200,
30+
"message": "OK"
31+
},
32+
"headers": {
33+
"Age": [
34+
"0"
35+
],
36+
"Connection": [
37+
"keep-alive"
38+
],
39+
"Content-Type": [
40+
"text/javascript; charset=\"UTF-8\""
41+
],
42+
"Content-Length": [
43+
"52"
44+
],
45+
"Cache-Control": [
46+
"no-cache"
47+
],
48+
"Server": [
49+
"Pubnub Storage"
50+
],
51+
"Date": [
52+
"Wed, 22 Nov 2023 15:33:23 GMT"
53+
],
54+
"Access-Control-Allow-Origin": [
55+
"*"
56+
],
57+
"Access-Control-Allow-Methods": [
58+
"GET, POST, DELETE, OPTIONS"
59+
],
60+
"Accept-Ranges": [
61+
"bytes"
62+
]
63+
},
64+
"body": {
65+
"string": "{\"status\": 200, \"error\": false, \"error_message\": \"\"}"
66+
}
67+
}
68+
},
69+
{
70+
"request": {
71+
"method": "GET",
72+
"uri": "https://ps.pndsn.com/publish/{PN_KEY_PUBLISH}/{PN_KEY_SUBSCRIBE}/0/test_unencrypted/0/%22Lorem%20Ipsum%22?seqn=1",
73+
"body": null,
74+
"headers": {
75+
"User-Agent": [
76+
"PubNub-Python/7.3.0"
77+
],
78+
"Accept-Encoding": [
79+
"gzip, deflate"
80+
],
81+
"Accept": [
82+
"*/*"
83+
],
84+
"Connection": [
85+
"keep-alive"
86+
]
87+
}
88+
},
89+
"response": {
90+
"status": {
91+
"code": 200,
92+
"message": "OK"
93+
},
94+
"headers": {
95+
"Connection": [
96+
"keep-alive"
97+
],
98+
"Content-Type": [
99+
"text/javascript; charset=\"UTF-8\""
100+
],
101+
"Content-Length": [
102+
"30"
103+
],
104+
"Cache-Control": [
105+
"no-cache"
106+
],
107+
"Date": [
108+
"Wed, 22 Nov 2023 15:33:23 GMT"
109+
],
110+
"Access-Control-Allow-Origin": [
111+
"*"
112+
],
113+
"Access-Control-Allow-Methods": [
114+
"GET"
115+
]
116+
},
117+
"body": {
118+
"string": "[1,\"Sent\",\"17006672033304156\"]"
119+
}
120+
}
121+
},
122+
{
123+
"request": {
124+
"method": "GET",
125+
"uri": "https://ps.pndsn.com/v2/history/sub-key/{PN_KEY_SUBSCRIBE}/channel/test_unencrypted?count=100",
126+
"body": null,
127+
"headers": {
128+
"User-Agent": [
129+
"PubNub-Python/7.3.0"
130+
],
131+
"Accept-Encoding": [
132+
"gzip, deflate"
133+
],
134+
"Accept": [
135+
"*/*"
136+
],
137+
"Connection": [
138+
"keep-alive"
139+
]
140+
}
141+
},
142+
"response": {
143+
"status": {
144+
"code": 200,
145+
"message": "OK"
146+
},
147+
"headers": {
148+
"Age": [
149+
"0"
150+
],
151+
"Connection": [
152+
"keep-alive"
153+
],
154+
"Content-Type": [
155+
"text/javascript; charset=\"UTF-8\""
156+
],
157+
"Content-Length": [
158+
"53"
159+
],
160+
"Cache-Control": [
161+
"no-cache"
162+
],
163+
"Server": [
164+
"Pubnub Storage"
165+
],
166+
"Date": [
167+
"Wed, 22 Nov 2023 15:33:25 GMT"
168+
],
169+
"Access-Control-Allow-Origin": [
170+
"*"
171+
],
172+
"Access-Control-Allow-Methods": [
173+
"GET, POST, DELETE, OPTIONS"
174+
],
175+
"Accept-Ranges": [
176+
"bytes"
177+
]
178+
},
179+
"body": {
180+
"string": "[[\"Lorem Ipsum\"],17006672033304156,17006672033304156]"
181+
}
182+
}
183+
}
184+
]
185+
}

tests/integrational/native_sync/test_history.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import binascii
12
import logging
23
import time
34
import unittest
@@ -9,7 +10,7 @@
910
from pubnub.models.consumer.history import PNHistoryResult
1011
from pubnub.models.consumer.pubsub import PNPublishResult
1112
from pubnub.pubnub import PubNub
12-
from tests.helper import pnconf_copy, pnconf_enc_copy, pnconf_pam_copy
13+
from tests.helper import pnconf_copy, pnconf_enc_copy, pnconf_enc_env_copy, pnconf_env_copy, pnconf_pam_copy
1314
from tests.integrational.vcr_helper import use_cassette_and_stub_time_sleep_native
1415

1516
pubnub.set_stream_logger('pubnub', logging.DEBUG)
@@ -104,3 +105,30 @@ def test_super_call_with_all_params(self):
104105
assert isinstance(envelope.result, PNHistoryResult)
105106

106107
assert not envelope.status.is_error()
108+
109+
110+
class TestHistoryCrypto(unittest.TestCase):
111+
@use_cassette_and_stub_time_sleep_native('tests/integrational/fixtures/native_sync/history/unencrypted.json',
112+
serializer='pn_json', filter_query_parameters=['uuid', 'pnsdk'])
113+
def test_unencrypted(self):
114+
ch = "test_unencrypted"
115+
pubnub = PubNub(pnconf_env_copy())
116+
pubnub.config.uuid = "history-native-sync-uuid"
117+
pubnub.delete_messages().channel(ch).sync()
118+
envelope = pubnub.publish().channel(ch).message("Lorem Ipsum").sync()
119+
assert isinstance(envelope.result, PNPublishResult)
120+
assert envelope.result.timetoken > 0
121+
122+
time.sleep(2)
123+
124+
pubnub_enc = PubNub(pnconf_enc_env_copy())
125+
pubnub_enc.config.uuid = "history-native-sync-uuid"
126+
envelope = pubnub_enc.history().channel(ch).sync()
127+
128+
assert isinstance(envelope.result, PNHistoryResult)
129+
assert envelope.result.start_timetoken > 0
130+
assert envelope.result.end_timetoken > 0
131+
assert len(envelope.result.messages) == 1
132+
133+
assert envelope.result.messages[0].entry == 'Lorem Ipsum'
134+
assert isinstance(envelope.result.messages[0].error, binascii.Error)

0 commit comments

Comments
 (0)