From ebf73598fa310429b9f79b280be83a46df01d796 Mon Sep 17 00:00:00 2001 From: Jonathan Edey Date: Tue, 24 Oct 2023 11:30:25 -0400 Subject: [PATCH 1/4] feat(fcm): Enabled direct_boot_ok Android Config parameter. --- firebase_admin/_messaging_encoder.py | 11 +++++++++++ firebase_admin/_messaging_utils.py | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/firebase_admin/_messaging_encoder.py b/firebase_admin/_messaging_encoder.py index 48a3dd3cd..725db45cc 100644 --- a/firebase_admin/_messaging_encoder.py +++ b/firebase_admin/_messaging_encoder.py @@ -160,6 +160,15 @@ def check_analytics_label(cls, label, value): raise ValueError('Malformed {}.'.format(label)) return value + @classmethod + def check_boolean(cls, label, value): + """Checks if the given value is boolean.""" + if value is None: + return None + if not isinstance(value, bool): + raise ValueError('{0} must be a boolean.'.format(label)) + return value + @classmethod def check_datetime(cls, label, value): """Checks if the given value is a datetime.""" @@ -214,6 +223,8 @@ def encode_android_fcm_options(cls, fcm_options): result = { 'analytics_label': _Validators.check_analytics_label( 'AndroidFCMOptions.analytics_label', fcm_options.analytics_label), + 'direct_boot_ok': _Validators.check_boolean( + 'AndroidFCMOptions.direct_boot_ok', fcm_options.direct_boot_ok) } result = cls.remove_null_values(result) return result diff --git a/firebase_admin/_messaging_utils.py b/firebase_admin/_messaging_utils.py index 64930f1b8..e10b869bd 100644 --- a/firebase_admin/_messaging_utils.py +++ b/firebase_admin/_messaging_utils.py @@ -203,10 +203,13 @@ class AndroidFCMOptions: Args: analytics_label: contains additional options for features provided by the FCM Android SDK (optional). + direct_boot_ok: A boolean indicating whether messages will be allowed to be delivered to + the app while the device is in direct boot mode. """ - def __init__(self, analytics_label=None): + def __init__(self, analytics_label=None, direct_boot_ok=None): self.analytics_label = analytics_label + self.direct_boot_ok = direct_boot_ok class WebpushConfig: From 60bcb7bce529e469eb5fdf6532543ead6c58ffca Mon Sep 17 00:00:00 2001 From: Jonathan Edey Date: Tue, 24 Oct 2023 11:32:51 -0400 Subject: [PATCH 2/4] Added tests. --- tests/test_messaging.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/test_messaging.py b/tests/test_messaging.py index 71bb13eed..895448e9e 100644 --- a/tests/test_messaging.py +++ b/tests/test_messaging.py @@ -33,6 +33,7 @@ NON_OBJECT_ARGS = [list(), tuple(), dict(), 'foo', 0, 1, True, False] NON_LIST_ARGS = ['', tuple(), dict(), True, False, 1, 0, [1], ['foo', 1]] NON_UINT_ARGS = ['1.23s', list(), tuple(), dict(), -1.23] +NON_BOOL_ARGS = ['', list(), tuple(), dict(), 1, 0, [1], ['foo', 1], {1: 'foo'}, {'foo': 1}] HTTP_ERROR_CODES = { 400: exceptions.InvalidArgumentError, 403: exceptions.PermissionDeniedError, @@ -249,7 +250,7 @@ def test_fcm_options(self): topic='topic', fcm_options=messaging.FCMOptions('message-label'), android=messaging.AndroidConfig( - fcm_options=messaging.AndroidFCMOptions('android-label')), + fcm_options=messaging.AndroidFCMOptions('android-label', False)), apns=messaging.APNSConfig(fcm_options= messaging.APNSFCMOptions( analytics_label='apns-label', @@ -259,7 +260,8 @@ def test_fcm_options(self): { 'topic': 'topic', 'fcm_options': {'analytics_label': 'message-label'}, - 'android': {'fcm_options': {'analytics_label': 'android-label'}}, + 'android': {'fcm_options': {'analytics_label': 'android-label', + 'direct_boot_ok': False,}}, 'apns': {'fcm_options': {'analytics_label': 'apns-label', 'image': 'https://images.unsplash.com/photo-14944386399' '46-1ebd1d20bf85?fit=crop&w=900&q=60'}}, @@ -317,6 +319,21 @@ def test_invalid_data(self, data): check_encoding(messaging.Message( topic='topic', android=messaging.AndroidConfig(data=data))) + @pytest.mark.parametrize('data', NON_STRING_ARGS) + def test_invalid_analytics_label(self, data): + with pytest.raises(ValueError): + check_encoding(messaging.Message( + topic='topic', android=messaging.AndroidConfig( + fcm_options=messaging.AndroidFCMOptions(analytics_label=data)))) + + @pytest.mark.parametrize('data', NON_BOOL_ARGS) + def test_invalid_direct_boot_ok(self, data): + with pytest.raises(ValueError): + check_encoding(messaging.Message( + topic='topic', android=messaging.AndroidConfig( + fcm_options=messaging.AndroidFCMOptions(direct_boot_ok=data)))) + + def test_android_config(self): msg = messaging.Message( topic='topic', @@ -326,7 +343,7 @@ def test_android_config(self): priority='high', ttl=123, data={'k1': 'v1', 'k2': 'v2'}, - fcm_options=messaging.AndroidFCMOptions('analytics_label_v1') + fcm_options=messaging.AndroidFCMOptions('analytics_label_v1', True) ) ) expected = { @@ -342,6 +359,7 @@ def test_android_config(self): }, 'fcm_options': { 'analytics_label': 'analytics_label_v1', + 'direct_boot_ok': True, }, }, } From d2924f088e6ef660390ffa397f3c9ccc7c5e033e Mon Sep 17 00:00:00 2001 From: Jonathan Edey Date: Tue, 24 Oct 2023 12:19:42 -0400 Subject: [PATCH 3/4] fix: add to correct config. --- firebase_admin/_messaging_encoder.py | 4 ++-- firebase_admin/_messaging_utils.py | 10 +++++----- tests/test_messaging.py | 15 ++++++++------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/firebase_admin/_messaging_encoder.py b/firebase_admin/_messaging_encoder.py index 725db45cc..9910e5541 100644 --- a/firebase_admin/_messaging_encoder.py +++ b/firebase_admin/_messaging_encoder.py @@ -205,6 +205,8 @@ def encode_android(cls, android): 'AndroidConfig.restricted_package_name', android.restricted_package_name), 'ttl': cls.encode_ttl(android.ttl), 'fcm_options': cls.encode_android_fcm_options(android.fcm_options), + 'direct_boot_ok': _Validators.check_boolean( + 'AndroidFCMOptions.direct_boot_ok', android.direct_boot_ok), } result = cls.remove_null_values(result) priority = result.get('priority') @@ -223,8 +225,6 @@ def encode_android_fcm_options(cls, fcm_options): result = { 'analytics_label': _Validators.check_analytics_label( 'AndroidFCMOptions.analytics_label', fcm_options.analytics_label), - 'direct_boot_ok': _Validators.check_boolean( - 'AndroidFCMOptions.direct_boot_ok', fcm_options.direct_boot_ok) } result = cls.remove_null_values(result) return result diff --git a/firebase_admin/_messaging_utils.py b/firebase_admin/_messaging_utils.py index e10b869bd..29b8276bc 100644 --- a/firebase_admin/_messaging_utils.py +++ b/firebase_admin/_messaging_utils.py @@ -49,10 +49,12 @@ class AndroidConfig: strings. When specified, overrides any data fields set via ``Message.data``. notification: A ``messaging.AndroidNotification`` to be included in the message (optional). fcm_options: A ``messaging.AndroidFCMOptions`` to be included in the message (optional). + direct_boot_ok: A boolean indicating whether messages will be allowed to be delivered to + the app while the device is in direct boot mode (optional). """ def __init__(self, collapse_key=None, priority=None, ttl=None, restricted_package_name=None, - data=None, notification=None, fcm_options=None): + data=None, notification=None, fcm_options=None, direct_boot_ok=None): self.collapse_key = collapse_key self.priority = priority self.ttl = ttl @@ -60,6 +62,7 @@ def __init__(self, collapse_key=None, priority=None, ttl=None, restricted_packag self.data = data self.notification = notification self.fcm_options = fcm_options + self.direct_boot_ok = direct_boot_ok class AndroidNotification: @@ -203,13 +206,10 @@ class AndroidFCMOptions: Args: analytics_label: contains additional options for features provided by the FCM Android SDK (optional). - direct_boot_ok: A boolean indicating whether messages will be allowed to be delivered to - the app while the device is in direct boot mode. """ - def __init__(self, analytics_label=None, direct_boot_ok=None): + def __init__(self, analytics_label=None): self.analytics_label = analytics_label - self.direct_boot_ok = direct_boot_ok class WebpushConfig: diff --git a/tests/test_messaging.py b/tests/test_messaging.py index 895448e9e..5072df6ea 100644 --- a/tests/test_messaging.py +++ b/tests/test_messaging.py @@ -250,7 +250,8 @@ def test_fcm_options(self): topic='topic', fcm_options=messaging.FCMOptions('message-label'), android=messaging.AndroidConfig( - fcm_options=messaging.AndroidFCMOptions('android-label', False)), + fcm_options=messaging.AndroidFCMOptions('android-label'), + direct_boot_ok=False), apns=messaging.APNSConfig(fcm_options= messaging.APNSFCMOptions( analytics_label='apns-label', @@ -260,8 +261,8 @@ def test_fcm_options(self): { 'topic': 'topic', 'fcm_options': {'analytics_label': 'message-label'}, - 'android': {'fcm_options': {'analytics_label': 'android-label', - 'direct_boot_ok': False,}}, + 'android': {'fcm_options': {'analytics_label': 'android-label'}, + 'direct_boot_ok': False}, 'apns': {'fcm_options': {'analytics_label': 'apns-label', 'image': 'https://images.unsplash.com/photo-14944386399' '46-1ebd1d20bf85?fit=crop&w=900&q=60'}}, @@ -330,8 +331,7 @@ def test_invalid_analytics_label(self, data): def test_invalid_direct_boot_ok(self, data): with pytest.raises(ValueError): check_encoding(messaging.Message( - topic='topic', android=messaging.AndroidConfig( - fcm_options=messaging.AndroidFCMOptions(direct_boot_ok=data)))) + topic='topic', android=messaging.AndroidConfig(direct_boot_ok=data))) def test_android_config(self): @@ -343,7 +343,8 @@ def test_android_config(self): priority='high', ttl=123, data={'k1': 'v1', 'k2': 'v2'}, - fcm_options=messaging.AndroidFCMOptions('analytics_label_v1', True) + fcm_options=messaging.AndroidFCMOptions('analytics_label_v1'), + direct_boot_ok=True, ) ) expected = { @@ -359,8 +360,8 @@ def test_android_config(self): }, 'fcm_options': { 'analytics_label': 'analytics_label_v1', - 'direct_boot_ok': True, }, + 'direct_boot_ok': True, }, } check_encoding(msg, expected) From b6bc928288b57867b9e210b51ddce3dbf5e4e329 Mon Sep 17 00:00:00 2001 From: Jonathan Edey Date: Wed, 15 Nov 2023 11:49:50 -0500 Subject: [PATCH 4/4] fix: Validator label --- firebase_admin/_messaging_encoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase_admin/_messaging_encoder.py b/firebase_admin/_messaging_encoder.py index 9910e5541..85072b597 100644 --- a/firebase_admin/_messaging_encoder.py +++ b/firebase_admin/_messaging_encoder.py @@ -206,7 +206,7 @@ def encode_android(cls, android): 'ttl': cls.encode_ttl(android.ttl), 'fcm_options': cls.encode_android_fcm_options(android.fcm_options), 'direct_boot_ok': _Validators.check_boolean( - 'AndroidFCMOptions.direct_boot_ok', android.direct_boot_ok), + 'AndroidConfig.direct_boot_ok', android.direct_boot_ok), } result = cls.remove_null_values(result) priority = result.get('priority')