Skip to content

Commit a16efdf

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feature/dependency_upgrades
2 parents bde39dc + 927545f commit a16efdf

File tree

6 files changed

+185
-6
lines changed

6 files changed

+185
-6
lines changed

bunq/sdk/model/core/bunq_model.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import typing
44
from typing import Dict, List
55

6+
from bunq import T
67
from bunq.sdk.http.bunq_response import BunqResponse
78
from bunq.sdk.http.bunq_response_raw import BunqResponseRaw
89
from bunq.sdk.json import converter
@@ -90,7 +91,7 @@ def _process_for_uuid(cls, response_raw: BunqResponseRaw) -> BunqResponse[str]:
9091
@classmethod
9192
def _from_json_list(cls,
9293
response_raw: BunqResponseRaw,
93-
wrapper: str = None) -> BunqResponse[List[BunqModel]]:
94+
wrapper: str = None) -> BunqResponse[List[T]]:
9495
from bunq import Pagination
9596

9697
json = response_raw.body_bytes.decode()
@@ -103,7 +104,10 @@ def _from_json_list(cls,
103104
item_deserialized = converter.deserialize(cls, item_unwrapped)
104105
array_deserialized.append(item_deserialized)
105106

106-
pagination = converter.deserialize(Pagination, obj[cls._FIELD_PAGINATION])
107+
pagination = None
108+
109+
if cls._FIELD_PAGINATION in obj:
110+
pagination = converter.deserialize(Pagination, obj[cls._FIELD_PAGINATION])
107111

108112
return BunqResponse(array_deserialized, response_raw.headers, pagination)
109113

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from __future__ import annotations
2+
3+
from typing import List, Dict
4+
5+
from bunq.sdk.http.api_client import ApiClient
6+
from bunq.sdk.http.bunq_response import BunqResponse
7+
from bunq.sdk.json import converter
8+
from bunq.sdk.model.generated.endpoint import NotificationFilterPushUser
9+
from bunq.sdk.model.generated.object_ import NotificationFilterPush, NotificationFilterUrl
10+
11+
12+
class NotificationFilterPushUserInternal(NotificationFilterPushUser):
13+
@classmethod
14+
def create_with_list_response(cls,
15+
all_notification_filter: List[NotificationFilterPush] = None,
16+
custom_headers: Dict[str, str] = None
17+
) -> BunqResponse[List[NotificationFilterPush]]:
18+
if all_notification_filter is None:
19+
all_notification_filter = []
20+
21+
if custom_headers is None:
22+
custom_headers = {}
23+
24+
request_map = {
25+
cls.FIELD_NOTIFICATION_FILTERS: all_notification_filter
26+
}
27+
request_map_string = converter.class_to_json(request_map)
28+
request_map_string = cls._remove_field_for_request(request_map_string)
29+
30+
api_client = ApiClient(cls._get_api_context())
31+
request_bytes = request_map_string.encode()
32+
endpoint_url = cls._ENDPOINT_URL_CREATE.format(cls._determine_user_id())
33+
response_raw = api_client.post(endpoint_url, request_bytes, custom_headers)
34+
35+
return NotificationFilterUrl._from_json_list(response_raw, cls._OBJECT_TYPE_GET)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from __future__ import annotations
2+
3+
from typing import List, Dict
4+
5+
from bunq.sdk.http.api_client import ApiClient
6+
from bunq.sdk.http.bunq_response import BunqResponse
7+
from bunq.sdk.json import converter
8+
from bunq.sdk.model.generated.endpoint import NotificationFilterUrlMonetaryAccount
9+
from bunq.sdk.model.generated.object_ import NotificationFilterUrl
10+
11+
12+
class NotificationFilterUrlMonetaryAccountInternal(NotificationFilterUrlMonetaryAccount):
13+
@classmethod
14+
def create_with_list_response(cls,
15+
monetary_account_id: int = None,
16+
all_notification_filter: List[NotificationFilterUrl] = None,
17+
custom_headers: Dict[str, str] = None
18+
) -> BunqResponse[List[NotificationFilterUrl]]:
19+
if all_notification_filter is None:
20+
all_notification_filter = []
21+
22+
if custom_headers is None:
23+
custom_headers = {}
24+
25+
request_map = {
26+
cls.FIELD_NOTIFICATION_FILTERS: all_notification_filter
27+
}
28+
request_map_string = converter.class_to_json(request_map)
29+
request_map_string = cls._remove_field_for_request(request_map_string)
30+
31+
api_client = ApiClient(cls._get_api_context())
32+
request_bytes = request_map_string.encode()
33+
endpoint_url = cls._ENDPOINT_URL_CREATE.format(cls._determine_user_id(),
34+
cls._determine_monetary_account_id(monetary_account_id))
35+
response_raw = api_client.post(endpoint_url, request_bytes, custom_headers)
36+
37+
return NotificationFilterUrl._from_json_list(response_raw, cls._OBJECT_TYPE_GET)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from __future__ import annotations
2+
3+
from typing import List, Dict
4+
5+
from bunq.sdk.http.api_client import ApiClient
6+
from bunq.sdk.http.bunq_response import BunqResponse
7+
from bunq.sdk.json import converter
8+
from bunq.sdk.model.generated.endpoint import NotificationFilterUrlUser
9+
from bunq.sdk.model.generated.object_ import NotificationFilterUrl
10+
11+
12+
class NotificationFilterUrlUserInternal(NotificationFilterUrlUser):
13+
@classmethod
14+
def create_with_list_response(cls,
15+
all_notification_filter: List[NotificationFilterUrl] = None,
16+
custom_headers: Dict[str, str] = None
17+
) -> BunqResponse[List[NotificationFilterUrl]]:
18+
if all_notification_filter is None:
19+
all_notification_filter = []
20+
21+
if custom_headers is None:
22+
custom_headers = {}
23+
24+
request_map = {
25+
cls.FIELD_NOTIFICATION_FILTERS: all_notification_filter
26+
}
27+
request_map_string = converter.class_to_json(request_map)
28+
request_map_string = cls._remove_field_for_request(request_map_string)
29+
30+
api_client = ApiClient(cls._get_api_context())
31+
request_bytes = request_map_string.encode()
32+
endpoint_url = cls._ENDPOINT_URL_CREATE.format(cls._determine_user_id())
33+
response_raw = api_client.post(endpoint_url, request_bytes, custom_headers)
34+
35+
return NotificationFilterUrl._from_json_list(response_raw, cls._OBJECT_TYPE_GET)

bunq/sdk/security/security.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,14 @@ def validate_response(public_key_server: RsaKey,
187187

188188

189189
def is_valid_response_header_with_body(public_key_server: RsaKey,
190-
status_code: int,
191-
body_bytes: bytes,
192-
headers: Dict[str, str]) -> bool:
190+
status_code: int,
191+
body_bytes: bytes,
192+
headers: Dict[str, str]) -> bool:
193193
head_bytes = _generate_response_head_bytes(status_code, headers)
194194
bytes_signed = head_bytes + body_bytes
195195
signer = PKCS1_v1_5.pkcs1_15.new(public_key_server)
196196
digest = SHA256.new()
197197
digest.update(bytes_signed)
198-
signer.verify(digest, base64.b64decode(headers[_HEADER_SERVER_SIGNATURE]))
199198

200199
try:
201200
signer.verify(digest, base64.b64decode(headers[_HEADER_SERVER_SIGNATURE]))
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from bunq.sdk.context.bunq_context import BunqContext
2+
from bunq.sdk.model.core.notification_filter_push_user_internal import NotificationFilterPushUserInternal
3+
from bunq.sdk.model.core.notification_filter_url_monetary_account_internal import \
4+
NotificationFilterUrlMonetaryAccountInternal
5+
from bunq.sdk.model.core.notification_filter_url_user_internal import NotificationFilterUrlUserInternal
6+
from bunq.sdk.model.generated.object_ import NotificationFilterUrl, NotificationFilterPush
7+
from tests.bunq_test import BunqSdkTestCase
8+
9+
10+
class TestNotificationFilter(BunqSdkTestCase):
11+
_FILTER_CATEGORY_MUTATION = 'MUTATION'
12+
_FILTER_CALLBACK_URL = 'https://test.com/callback'
13+
14+
def test_notification_filter_url_monetary_account(self):
15+
notification_filter = self.get_notification_filter_url()
16+
all_notification_filter = [notification_filter]
17+
18+
all_created_notification_filter = NotificationFilterUrlMonetaryAccountInternal.create_with_list_response(
19+
self.get_primary_monetary_account().id_,
20+
all_notification_filter
21+
).value
22+
23+
self.assertEqual(1, len(all_created_notification_filter))
24+
25+
def test_notification_filter_url_user(self):
26+
notification_filter = self.get_notification_filter_url()
27+
all_notification_filter = [notification_filter]
28+
29+
all_created_notification_filter = NotificationFilterUrlUserInternal.create_with_list_response(
30+
all_notification_filter
31+
).value
32+
33+
self.assertEqual(1, len(all_created_notification_filter))
34+
35+
def test_notification_filter_push_user(self):
36+
notification_filter = self.get_notification_filter_push()
37+
all_notification_filter = [notification_filter]
38+
39+
all_created_notification_filter = NotificationFilterPushUserInternal.create_with_list_response(
40+
all_notification_filter
41+
).value
42+
43+
self.assertEqual(1, len(all_created_notification_filter))
44+
45+
def test_notification_filter_clear(self):
46+
all_created_notification_filter_push_user = \
47+
NotificationFilterPushUserInternal.create_with_list_response().value
48+
all_created_notification_filter_url_user = \
49+
NotificationFilterUrlUserInternal.create_with_list_response().value
50+
all_created_notification_filter_url_monetary_account = \
51+
NotificationFilterUrlMonetaryAccountInternal.create_with_list_response().value
52+
53+
self.assertFalse(all_created_notification_filter_push_user)
54+
self.assertFalse(all_created_notification_filter_url_user)
55+
self.assertFalse(all_created_notification_filter_url_monetary_account)
56+
57+
self.assertEqual(0, len(NotificationFilterPushUserInternal.list().value))
58+
self.assertEqual(0, len(NotificationFilterUrlUserInternal.list().value))
59+
self.assertEqual(0, len(NotificationFilterUrlMonetaryAccountInternal.list().value))
60+
61+
def get_notification_filter_url(self):
62+
return NotificationFilterUrl(self._FILTER_CATEGORY_MUTATION, self._FILTER_CALLBACK_URL)
63+
64+
def get_notification_filter_push(self):
65+
return NotificationFilterPush(self._FILTER_CATEGORY_MUTATION)
66+
67+
@staticmethod
68+
def get_primary_monetary_account():
69+
return BunqContext.user_context().primary_monetary_account

0 commit comments

Comments
 (0)