From 1b25d4be002b1347b56d2c7c38e8fbedc54b6e6f Mon Sep 17 00:00:00 2001 From: Pragati Date: Thu, 16 Mar 2023 17:18:05 -0700 Subject: [PATCH 1/8] feat(auth): Add Email Privacy support in Project and Tenant config --- firebase_admin/email_privacy_config_mgt.py | 86 ++++++++++++++++++++++ firebase_admin/project_config_mgt.py | 25 ++++++- firebase_admin/tenant_mgt.py | 35 +++++++-- 3 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 firebase_admin/email_privacy_config_mgt.py diff --git a/firebase_admin/email_privacy_config_mgt.py b/firebase_admin/email_privacy_config_mgt.py new file mode 100644 index 000000000..601eb2dba --- /dev/null +++ b/firebase_admin/email_privacy_config_mgt.py @@ -0,0 +1,86 @@ +# Copyright 2023 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Firebase multifactor configuration management module. + +This module contains functions for managing various multifactor configurations at +the project and tenant level. +""" +from enum import Enum +from typing import List + +__all__ = [ + 'validate_keys', + 'EmailPrivacyServerConfig', + 'EmailPrivacyConfig', +] + + +def validate_keys(keys, valid_keys, config_name): + for key in keys: + if key not in valid_keys: + raise ValueError( + '"{0}" is not a valid "{1}" parameter.'.format( + key, config_name)) + + +class EmailPrivacyServerConfig: + """Represents email privacy configuration response received from the server and + converts it to user format. + """ + + def __init__(self, data): + if not isinstance(data, dict): + raise ValueError( + 'Invalid data argument in EmailPrivacyConfig constructor: {0}'.format(data)) + self._data = data + + @property + def enable_improved_email_privacy(self): + return self._data.get('enableImprovedEmailPrivacy', False) + + +class EmailPrivacyConfig: + """Represents a email privacy configuration for tenant or project + """ + + def __init__(self, + enable_improved_email_privacy: bool = False): + self.enable_improved_email_privacy: bool = enable_improved_email_privacy + + def to_dict(self) -> dict: + data = {} + if self.enable_improved_email_privacy: + data['enableImprovedEmailPrivacy'] = self.enable_improved_email_privacy + return data + + def validate(self): + """Validates a given email_privacy_config object. + + Raises: + ValueError: In case of an unsuccessful validation. + """ + validate_keys( + keys=vars(self).keys(), + valid_keys={'enable_improved_email_privacy'}, + config_name='EmailPrivacyConfig') + if self.enable_improved_email_privacy is None: + raise ValueError( + 'email_privacy_config.enable_improved_email_privacy must be specified') + if not isinstance(self.enable_improved_email_privacy, bool): + raise ValueError( + 'enable_improved_email_privacy must be a valid bool.') + + def build_server_request(self): + self.validate() + return self.to_dict() diff --git a/firebase_admin/project_config_mgt.py b/firebase_admin/project_config_mgt.py index df123e261..4f9ae340a 100644 --- a/firebase_admin/project_config_mgt.py +++ b/firebase_admin/project_config_mgt.py @@ -24,6 +24,7 @@ from firebase_admin import _utils from firebase_admin.multi_factor_config_mgt import MultiFactorConfig from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig +from firebase_admin import email_privacy_config_mgt _PROJECT_CONFIG_MGT_ATTRIBUTE = '_project_config_mgt' @@ -52,7 +53,9 @@ def get_project_config(app=None): project_config_mgt_service = _get_project_config_mgt_service(app) return project_config_mgt_service.get_project_config() -def update_project_config(multi_factor_config: MultiFactorConfig = None, app=None): +def update_project_config(multi_factor_config: MultiFactorConfig = None, + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, + app=None): """Update the Project Config with the given options. Args: multi_factor_config: Updated Multi Factor Authentication configuration @@ -65,7 +68,8 @@ def update_project_config(multi_factor_config: MultiFactorConfig = None, app=Non FirebaseError: If an error occurs while updating the project. """ project_config_mgt_service = _get_project_config_mgt_service(app) - return project_config_mgt_service.update_project_config(multi_factor_config=multi_factor_config) + return project_config_mgt_service.update_project_config(multi_factor_config=multi_factor_config, + email_privacy_config=email_privacy_config) def _get_project_config_mgt_service(app): @@ -89,6 +93,13 @@ def multi_factor_config(self): return MultiFactorServerConfig(data) return None + @property + def email_privacy_config(self): + data = self._data.get('emailPrivacyConfig') + if data: + return email_privacy_config_mgt.EmailPrivacyServerConfig(data) + return None + class _ProjectConfigManagementService: """Firebase project management service.""" @@ -112,7 +123,9 @@ def get_project_config(self) -> ProjectConfig: else: return ProjectConfig(body) - def update_project_config(self, multi_factor_config: MultiFactorConfig = None) -> ProjectConfig: + def update_project_config(self, multi_factor_config: MultiFactorConfig = None, + email_privacy_config: + email_privacy_config_mgt.EmailPrivacyConfig = None) -> ProjectConfig: """Updates the specified project with the given parameters.""" payload = {} @@ -120,6 +133,12 @@ def update_project_config(self, multi_factor_config: MultiFactorConfig = None) - if not isinstance(multi_factor_config, MultiFactorConfig): raise ValueError('multi_factor_config must be of type MultiFactorConfig.') payload['mfa'] = multi_factor_config.build_server_request() + + if email_privacy_config is not None: + if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') + payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() + if not payload: raise ValueError( 'At least one parameter must be specified for update.') diff --git a/firebase_admin/tenant_mgt.py b/firebase_admin/tenant_mgt.py index af222ff02..85920c8d3 100644 --- a/firebase_admin/tenant_mgt.py +++ b/firebase_admin/tenant_mgt.py @@ -29,6 +29,7 @@ from firebase_admin import _auth_utils from firebase_admin import _http_client from firebase_admin import _utils +from firebase_admin import email_privacy_config_mgt _TENANT_MGT_ATTRIBUTE = '_tenant_mgt' @@ -93,7 +94,8 @@ def get_tenant(tenant_id, app=None): def create_tenant( display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, app=None): + multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, app=None): """Creates a new tenant from the given options. Args: @@ -104,6 +106,7 @@ def create_tenant( enable_email_link_sign_in: A boolean indicating whether to enable or disable email link sign-in (optional). Disabling this makes the password required for email sign-in. multi_factor_config : A multi factor configuration to add to the tenant (optional). + email_privacy_config: An email privacy configuration to add to the tenant (optional). app: An App instance (optional). Returns: @@ -117,12 +120,14 @@ def create_tenant( return tenant_mgt_service.create_tenant( display_name=display_name, allow_password_sign_up=allow_password_sign_up, enable_email_link_sign_in=enable_email_link_sign_in, - multi_factor_config=multi_factor_config,) + multi_factor_config=multi_factor_config, + email_privacy_config=email_privacy_config) def update_tenant( tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, app=None): + multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, app=None): """Updates an existing tenant with the given options. Args: @@ -133,6 +138,7 @@ def update_tenant( enable_email_link_sign_in: A boolean indicating whether to enable or disable email link sign-in. Disabling this makes the password required for email sign-in. multi_factor_config : A multi factor configuration to update for the tenant (optional). + email_privacy_config: An email privacy configuration to update for the tenant (optional). app: An App instance (optional). Returns: @@ -147,7 +153,7 @@ def update_tenant( return tenant_mgt_service.update_tenant( tenant_id, display_name=display_name, allow_password_sign_up=allow_password_sign_up, enable_email_link_sign_in=enable_email_link_sign_in, - multi_factor_config=multi_factor_config) + multi_factor_config=multi_factor_config, email_privacy_config=email_privacy_config) def delete_tenant(tenant_id, app=None): @@ -240,6 +246,13 @@ def multi_factor_config(self): if data is not None: return multi_factor_config_mgt.MultiFactorServerConfig(data) return None + + @property + def email_privacy_config(self): + data = self._data.get('emailPrivacyConfig') + if data: + return email_privacy_config_mgt.EmailPrivacyServerConfig(data) + return None class _TenantManagementService: @@ -286,7 +299,8 @@ def get_tenant(self, tenant_id): def create_tenant( self, display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None): + multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None): """Creates a new tenant from the given parameters.""" payload = {'displayName': _validate_display_name(display_name)} @@ -301,6 +315,10 @@ def create_tenant( raise ValueError( 'multi_factor_config must be of type MultiFactorConfig.') payload['mfaConfig'] = multi_factor_config.build_server_request() + if email_privacy_config is not None: + if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') + payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() try: body = self.client.body('post', '/tenants', json=payload) except requests.exceptions.RequestException as error: @@ -311,7 +329,8 @@ def create_tenant( def update_tenant( self, tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None): + multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None): """Updates the specified tenant with the given parameters.""" if not isinstance(tenant_id, str) or not tenant_id: raise ValueError('Tenant ID must be a non-empty string.') @@ -329,6 +348,10 @@ def update_tenant( if not isinstance(multi_factor_config, multi_factor_config_mgt.MultiFactorConfig): raise ValueError('multi_factor_config must be of type MultiFactorConfig.') payload['mfaConfig'] = multi_factor_config.build_server_request() + if email_privacy_config is not None: + if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') + payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() if not payload: raise ValueError('At least one parameter must be specified for update.') From 54ce37e7513f9552c407895f10f357494dee8624 Mon Sep 17 00:00:00 2001 From: Pragati Date: Fri, 17 Mar 2023 12:15:19 -0700 Subject: [PATCH 2/8] `project_config_mgt` changes wrt `email_privacy` and lint fixes --- firebase_admin/email_privacy_config_mgt.py | 3 --- firebase_admin/project_config_mgt.py | 10 ++++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/firebase_admin/email_privacy_config_mgt.py b/firebase_admin/email_privacy_config_mgt.py index 601eb2dba..2683b1d43 100644 --- a/firebase_admin/email_privacy_config_mgt.py +++ b/firebase_admin/email_privacy_config_mgt.py @@ -16,8 +16,6 @@ This module contains functions for managing various multifactor configurations at the project and tenant level. """ -from enum import Enum -from typing import List __all__ = [ 'validate_keys', @@ -49,7 +47,6 @@ def __init__(self, data): def enable_improved_email_privacy(self): return self._data.get('enableImprovedEmailPrivacy', False) - class EmailPrivacyConfig: """Represents a email privacy configuration for tenant or project """ diff --git a/firebase_admin/project_config_mgt.py b/firebase_admin/project_config_mgt.py index 4f9ae340a..f2b501f70 100644 --- a/firebase_admin/project_config_mgt.py +++ b/firebase_admin/project_config_mgt.py @@ -24,7 +24,7 @@ from firebase_admin import _utils from firebase_admin.multi_factor_config_mgt import MultiFactorConfig from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig -from firebase_admin import email_privacy_config_mgt +from firebase_admin import email_privacy_config_mgt _PROJECT_CONFIG_MGT_ATTRIBUTE = '_project_config_mgt' @@ -60,6 +60,7 @@ def update_project_config(multi_factor_config: MultiFactorConfig = None, Args: multi_factor_config: Updated Multi Factor Authentication configuration (optional) + email_privacy_config: Updated Email Privacy configuration (optional). app: An App instance (optional). Returns: Project: An updated ProjectConfig object. @@ -68,8 +69,9 @@ def update_project_config(multi_factor_config: MultiFactorConfig = None, FirebaseError: If an error occurs while updating the project. """ project_config_mgt_service = _get_project_config_mgt_service(app) - return project_config_mgt_service.update_project_config(multi_factor_config=multi_factor_config, - email_privacy_config=email_privacy_config) + return project_config_mgt_service.update_project_config(multi_factor_config=multi_factor_config, + email_privacy_config= + email_privacy_config) def _get_project_config_mgt_service(app): @@ -124,7 +126,7 @@ def get_project_config(self) -> ProjectConfig: return ProjectConfig(body) def update_project_config(self, multi_factor_config: MultiFactorConfig = None, - email_privacy_config: + email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None) -> ProjectConfig: """Updates the specified project with the given parameters.""" From 2f7ad5af9695d1bf3c331baad4e00f8171b89a8e Mon Sep 17 00:00:00 2001 From: Pragati Date: Fri, 17 Mar 2023 12:20:55 -0700 Subject: [PATCH 3/8] Lint changes --- firebase_admin/email_privacy_config_mgt.py | 2 +- firebase_admin/tenant_mgt.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase_admin/email_privacy_config_mgt.py b/firebase_admin/email_privacy_config_mgt.py index 2683b1d43..553c93550 100644 --- a/firebase_admin/email_privacy_config_mgt.py +++ b/firebase_admin/email_privacy_config_mgt.py @@ -46,7 +46,7 @@ def __init__(self, data): @property def enable_improved_email_privacy(self): return self._data.get('enableImprovedEmailPrivacy', False) - + class EmailPrivacyConfig: """Represents a email privacy configuration for tenant or project """ diff --git a/firebase_admin/tenant_mgt.py b/firebase_admin/tenant_mgt.py index 85920c8d3..54638b96b 100644 --- a/firebase_admin/tenant_mgt.py +++ b/firebase_admin/tenant_mgt.py @@ -246,7 +246,7 @@ def multi_factor_config(self): if data is not None: return multi_factor_config_mgt.MultiFactorServerConfig(data) return None - + @property def email_privacy_config(self): data = self._data.get('emailPrivacyConfig') From b572384397d87333a4fabcb0bc67d6151d984d0a Mon Sep 17 00:00:00 2001 From: Pragati Date: Wed, 20 Dec 2023 16:03:00 -0800 Subject: [PATCH 4/8] add unit tests + succint import types --- firebase_admin/project_config_mgt.py | 12 ++-- firebase_admin/tenant_mgt.py | 34 ++++++----- firebase_admin/test_email_privacy_config.py | 65 +++++++++++++++++++++ 3 files changed, 89 insertions(+), 22 deletions(-) create mode 100644 firebase_admin/test_email_privacy_config.py diff --git a/firebase_admin/project_config_mgt.py b/firebase_admin/project_config_mgt.py index f2b501f70..aa654a7a2 100644 --- a/firebase_admin/project_config_mgt.py +++ b/firebase_admin/project_config_mgt.py @@ -24,7 +24,8 @@ from firebase_admin import _utils from firebase_admin.multi_factor_config_mgt import MultiFactorConfig from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig -from firebase_admin import email_privacy_config_mgt +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig _PROJECT_CONFIG_MGT_ATTRIBUTE = '_project_config_mgt' @@ -54,7 +55,7 @@ def get_project_config(app=None): return project_config_mgt_service.get_project_config() def update_project_config(multi_factor_config: MultiFactorConfig = None, - email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, + email_privacy_config: EmailPrivacyConfig = None, app=None): """Update the Project Config with the given options. Args: @@ -99,7 +100,7 @@ def multi_factor_config(self): def email_privacy_config(self): data = self._data.get('emailPrivacyConfig') if data: - return email_privacy_config_mgt.EmailPrivacyServerConfig(data) + return EmailPrivacyServerConfig(data) return None class _ProjectConfigManagementService: @@ -126,8 +127,7 @@ def get_project_config(self) -> ProjectConfig: return ProjectConfig(body) def update_project_config(self, multi_factor_config: MultiFactorConfig = None, - email_privacy_config: - email_privacy_config_mgt.EmailPrivacyConfig = None) -> ProjectConfig: + email_privacy_config: EmailPrivacyConfig = None) -> ProjectConfig: """Updates the specified project with the given parameters.""" payload = {} @@ -137,7 +137,7 @@ def update_project_config(self, multi_factor_config: MultiFactorConfig = None, payload['mfa'] = multi_factor_config.build_server_request() if email_privacy_config is not None: - if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + if not isinstance(email_privacy_config, EmailPrivacyConfig): raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() diff --git a/firebase_admin/tenant_mgt.py b/firebase_admin/tenant_mgt.py index 54638b96b..6f30948a5 100644 --- a/firebase_admin/tenant_mgt.py +++ b/firebase_admin/tenant_mgt.py @@ -25,11 +25,13 @@ import firebase_admin from firebase_admin import auth -from firebase_admin import multi_factor_config_mgt from firebase_admin import _auth_utils from firebase_admin import _http_client from firebase_admin import _utils -from firebase_admin import email_privacy_config_mgt +from firebase_admin.multi_factor_config_mgt import MultiFactorConfig +from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig _TENANT_MGT_ATTRIBUTE = '_tenant_mgt' @@ -94,8 +96,8 @@ def get_tenant(tenant_id, app=None): def create_tenant( display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, - email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, app=None): + multi_factor_config: MultiFactorConfig = None, + email_privacy_config: EmailPrivacyConfig = None, app=None): """Creates a new tenant from the given options. Args: @@ -126,8 +128,8 @@ def create_tenant( def update_tenant( tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, - email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None, app=None): + multi_factor_config: MultiFactorConfig = None, + email_privacy_config: EmailPrivacyConfig = None, app=None): """Updates an existing tenant with the given options. Args: @@ -244,14 +246,14 @@ def enable_email_link_sign_in(self): def multi_factor_config(self): data = self._data.get('mfaConfig', None) if data is not None: - return multi_factor_config_mgt.MultiFactorServerConfig(data) + return MultiFactorServerConfig(data) return None @property def email_privacy_config(self): data = self._data.get('emailPrivacyConfig') if data: - return email_privacy_config_mgt.EmailPrivacyServerConfig(data) + return EmailPrivacyServerConfig(data) return None @@ -299,8 +301,8 @@ def get_tenant(self, tenant_id): def create_tenant( self, display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, - email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None): + multi_factor_config: MultiFactorConfig = None, + email_privacy_config: EmailPrivacyConfig = None): """Creates a new tenant from the given parameters.""" payload = {'displayName': _validate_display_name(display_name)} @@ -311,12 +313,12 @@ def create_tenant( payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( enable_email_link_sign_in, 'enableEmailLinkSignin') if multi_factor_config is not None: - if not isinstance(multi_factor_config, multi_factor_config_mgt.MultiFactorConfig): + if not isinstance(multi_factor_config, MultiFactorConfig): raise ValueError( 'multi_factor_config must be of type MultiFactorConfig.') payload['mfaConfig'] = multi_factor_config.build_server_request() if email_privacy_config is not None: - if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + if not isinstance(email_privacy_config, EmailPrivacyConfig): raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() try: @@ -329,8 +331,8 @@ def create_tenant( def update_tenant( self, tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - multi_factor_config: multi_factor_config_mgt.MultiFactorConfig = None, - email_privacy_config: email_privacy_config_mgt.EmailPrivacyConfig = None): + multi_factor_config: MultiFactorConfig = None, + email_privacy_config: EmailPrivacyConfig = None): """Updates the specified tenant with the given parameters.""" if not isinstance(tenant_id, str) or not tenant_id: raise ValueError('Tenant ID must be a non-empty string.') @@ -345,11 +347,11 @@ def update_tenant( payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( enable_email_link_sign_in, 'enableEmailLinkSignin') if multi_factor_config is not None: - if not isinstance(multi_factor_config, multi_factor_config_mgt.MultiFactorConfig): + if not isinstance(multi_factor_config, MultiFactorConfig): raise ValueError('multi_factor_config must be of type MultiFactorConfig.') payload['mfaConfig'] = multi_factor_config.build_server_request() if email_privacy_config is not None: - if not isinstance(email_privacy_config, email_privacy_config_mgt.EmailPrivacyConfig): + if not isinstance(email_privacy_config, EmailPrivacyConfig): raise ValueError('email_privacy_config must be of type EmailPrivacyConfig.') payload['emailPrivacyConfig'] = email_privacy_config.build_server_request() diff --git a/firebase_admin/test_email_privacy_config.py b/firebase_admin/test_email_privacy_config.py new file mode 100644 index 000000000..c6b6a44dd --- /dev/null +++ b/firebase_admin/test_email_privacy_config.py @@ -0,0 +1,65 @@ +# Copyright 2023 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from copy import copy + +import pytest + +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig + +sample_email_privacy_config = EmailPrivacyConfig( + enable_improved_email_privacy=True, +) + + +class TestEmailPrivacyConfig: + def test_invalid_email_privacy_config_params(self): + test_config = copy(sample_email_privacy_config) + test_config.invalid_parameter = 'invalid' + with pytest.raises(ValueError) as excinfo: + test_config.build_server_request() + assert str(excinfo.value).startswith('"invalid_parameter" is not a valid' + ' "EmailPrivacyConfig" parameter.') + + @pytest.mark.parametrize('enable_improved_email_privacy', + [{}, 1, 0, list(), tuple(), dict()]) + def test_invalid_enable_improved_email_privacy_type(self, enable_improved_email_privacy): + test_config = copy(sample_email_privacy_config) + test_config.enable_improved_email_privacy = enable_improved_email_privacy + with pytest.raises(ValueError) as excinfo: + test_config.build_server_request() + assert str(excinfo.value).startswith('provider_configs must be an array of type' + ' ProviderConfigs.') + + +class TestEmailPrivacyServerConfig: + def test_invalid_email_privacy_config_response(self): + test_config = 'invalid' + with pytest.raises(ValueError) as excinfo: + EmailPrivacyConfig(test_config) + assert str(excinfo.value).startswith('Invalid data argument in EmailPrivacyConfig' + ' constructor: {0}'.format(test_config)) + + def test_valid_server_response(self): + response = { + 'enableImprovedEmailPrivacy': 'true', + } + email_privacy_config = EmailPrivacyConfig(response) + _assert_email_privacy_config(email_privacy_config) + + +def _assert_email_privacy_config(email_privacy_config): + assert isinstance(email_privacy_config, EmailPrivacyServerConfig) + assert email_privacy_config.enable_improved_email_privacy is bool + assert email_privacy_config.enable_improved_email_privacy is True From bd1c367e1fb1db07ee9beb6a7e327646d4fe481f Mon Sep 17 00:00:00 2001 From: Pragati Date: Thu, 21 Dec 2023 14:45:15 -0800 Subject: [PATCH 5/8] add unit tests --- {firebase_admin => tests}/test_email_privacy_config.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) rename {firebase_admin => tests}/test_email_privacy_config.py (86%) diff --git a/firebase_admin/test_email_privacy_config.py b/tests/test_email_privacy_config.py similarity index 86% rename from firebase_admin/test_email_privacy_config.py rename to tests/test_email_privacy_config.py index c6b6a44dd..ea2efa2d7 100644 --- a/firebase_admin/test_email_privacy_config.py +++ b/tests/test_email_privacy_config.py @@ -39,27 +39,25 @@ def test_invalid_enable_improved_email_privacy_type(self, enable_improved_email_ test_config.enable_improved_email_privacy = enable_improved_email_privacy with pytest.raises(ValueError) as excinfo: test_config.build_server_request() - assert str(excinfo.value).startswith('provider_configs must be an array of type' - ' ProviderConfigs.') + assert str(excinfo.value).startswith('enable_improved_email_privacy must be a valid bool.') class TestEmailPrivacyServerConfig: def test_invalid_email_privacy_config_response(self): test_config = 'invalid' with pytest.raises(ValueError) as excinfo: - EmailPrivacyConfig(test_config) + EmailPrivacyServerConfig(test_config) assert str(excinfo.value).startswith('Invalid data argument in EmailPrivacyConfig' ' constructor: {0}'.format(test_config)) def test_valid_server_response(self): response = { - 'enableImprovedEmailPrivacy': 'true', + 'enableImprovedEmailPrivacy': True, } - email_privacy_config = EmailPrivacyConfig(response) + email_privacy_config = EmailPrivacyServerConfig(response) _assert_email_privacy_config(email_privacy_config) def _assert_email_privacy_config(email_privacy_config): assert isinstance(email_privacy_config, EmailPrivacyServerConfig) - assert email_privacy_config.enable_improved_email_privacy is bool assert email_privacy_config.enable_improved_email_privacy is True From 19e558558ec856d40685f45562cf4aaff33d9ed4 Mon Sep 17 00:00:00 2001 From: Pragati Date: Thu, 21 Dec 2023 16:32:18 -0800 Subject: [PATCH 6/8] add unit tests in project and tenant configs --- tests/test_project_config_mgt.py | 50 ++++++++++++---- tests/test_tenant_mgt.py | 97 +++++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 29 deletions(-) diff --git a/tests/test_project_config_mgt.py b/tests/test_project_config_mgt.py index 8d4775315..b4fa9b859 100644 --- a/tests/test_project_config_mgt.py +++ b/tests/test_project_config_mgt.py @@ -22,7 +22,12 @@ import firebase_admin from firebase_admin import project_config_mgt -from firebase_admin import multi_factor_config_mgt +from firebase_admin.multi_factor_config_mgt import MultiFactorConfig +from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig +from firebase_admin.multi_factor_config_mgt import ProviderConfig +from firebase_admin.multi_factor_config_mgt import TOTPProviderConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig ADJACENT_INTERVALS = 5 @@ -81,6 +86,9 @@ def test_project_config(self): } } ] + }, + 'emailPrivacyConfig': { + 'enableImprovedEmailPrivacy': True } } project_config = project_config_mgt.ProjectConfig(data) @@ -92,6 +100,7 @@ def test_project_optional_params(self): } project = project_config_mgt.ProjectConfig(data) assert project.multi_factor_config is None + assert project.email_privacy_config is None class TestGetProjectConfig: @@ -123,23 +132,37 @@ def test_invalid_multi_factor_config_type(self, multi_factor_config, project_con assert str(excinfo.value).startswith( 'multi_factor_config must be of type MultiFactorConfig.') + @pytest.mark.parametrize('email_privacy_config', ['a', 1, True, {}, dict(), list(), tuple()]) + def test_invalid_email_privacy_configs(self, email_privacy_config, project_config_mgt_app): + with pytest.raises(ValueError) as excinfo: + project_config_mgt.update_project_config(email_privacy_config=email_privacy_config, + app=project_config_mgt_app) + assert str(excinfo.value).startswith('email_privacy_config must be of type' + ' EmailPrivacyConfig.') + + def test_update_project_config(self, project_config_mgt_app): _, recorder = _instrument_project_config_mgt( project_config_mgt_app, 200, GET_PROJECT_RESPONSE) - mfa_object = multi_factor_config_mgt.MultiFactorConfig( + mfa_object = MultiFactorConfig( provider_configs=[ - multi_factor_config_mgt.ProviderConfig( - state=multi_factor_config_mgt.ProviderConfig.State.ENABLED, - totp_provider_config=multi_factor_config_mgt.TOTPProviderConfig( + ProviderConfig( + state=ProviderConfig.State.ENABLED, + totp_provider_config=TOTPProviderConfig( adjacent_intervals=ADJACENT_INTERVALS ) ) ] ) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) project_config = project_config_mgt.update_project_config( - multi_factor_config=mfa_object, app=project_config_mgt_app) + multi_factor_config=mfa_object, + email_privacy_config=email_privacy_object, + app=project_config_mgt_app) - mask = ['mfa.providerConfigs'] + mask = ['emailPrivacyConfig.enableImprovedEmailPrivacy', 'mfa.providerConfigs'] _assert_project_config(project_config) self._assert_request(recorder, { @@ -152,6 +175,9 @@ def test_update_project_config(self, project_config_mgt_app): } } ] + }, + 'emailPrivacyConfig': { + 'enableImprovedEmailPrivacy': True } }, mask) @@ -165,18 +191,22 @@ def _assert_request(self, recorder, body, mask): assert got == body def _assert_multi_factor_config(multi_factor_config): - assert isinstance(multi_factor_config, multi_factor_config_mgt.MultiFactorServerConfig) + assert isinstance(multi_factor_config, MultiFactorServerConfig) assert len(multi_factor_config.provider_configs) == 1 assert isinstance(multi_factor_config.provider_configs, list) for provider_config in multi_factor_config.provider_configs: - assert isinstance(provider_config, multi_factor_config_mgt.MultiFactorServerConfig + assert isinstance(provider_config, MultiFactorServerConfig .ProviderServerConfig) assert provider_config.state == 'ENABLED' assert isinstance(provider_config.totp_provider_config, - multi_factor_config_mgt.MultiFactorServerConfig.ProviderServerConfig + MultiFactorServerConfig.ProviderServerConfig .TOTPProviderServerConfig) assert provider_config.totp_provider_config.adjacent_intervals == ADJACENT_INTERVALS +def _assert_email_privacy_config(email_privacy_config): + assert isinstance(email_privacy_config, EmailPrivacyServerConfig) + assert email_privacy_config.enable_improved_email_privacy is True + def _assert_project_config(project_config): if project_config.multi_factor_config is not None: _assert_multi_factor_config(project_config.multi_factor_config) diff --git a/tests/test_tenant_mgt.py b/tests/test_tenant_mgt.py index 1a4a0372a..4da48bd52 100644 --- a/tests/test_tenant_mgt.py +++ b/tests/test_tenant_mgt.py @@ -26,7 +26,12 @@ from firebase_admin import tenant_mgt from firebase_admin import _auth_providers from firebase_admin import _user_mgt -from firebase_admin import multi_factor_config_mgt +from firebase_admin.multi_factor_config_mgt import MultiFactorConfig +from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig +from firebase_admin.multi_factor_config_mgt import ProviderConfig +from firebase_admin.multi_factor_config_mgt import TOTPProviderConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig from tests import testutils from tests import test_token_gen @@ -45,6 +50,9 @@ "adjacentIntervals": 5 } }] + }, + "emailPrivacyConfig": { + "enableImprovedEmailPrivacy": true } }""" @@ -187,6 +195,8 @@ def test_tenant_optional_params(self): assert tenant.display_name is None assert tenant.allow_password_sign_up is False assert tenant.enable_email_link_sign_in is False + assert tenant.multi_factor_config is None + assert tenant.email_privacy_config is None class TestGetTenant: @@ -251,25 +261,41 @@ def test_invalid_enable_email_link_sign_in(self, enable, tenant_mgt_app): def test_invalid_multi_factor_configs(self, multi_factor_config, tenant_mgt_app): with pytest.raises(ValueError) as excinfo: tenant_mgt.create_tenant( - display_name='test', multi_factor_config=multi_factor_config, app=tenant_mgt_app) + display_name='test', + multi_factor_config=multi_factor_config, + app=tenant_mgt_app) assert str(excinfo.value).startswith('multi_factor_config must be of type' ' MultiFactorConfig.') + @pytest.mark.parametrize('email_privacy_config', ['a', 1, True, {}, dict(), list(), tuple()]) + def test_invalid_email_privacy_configs(self, email_privacy_config, tenant_mgt_app): + with pytest.raises(ValueError) as excinfo: + tenant_mgt.create_tenant( + display_name='test', + email_privacy_config=email_privacy_config, + app=tenant_mgt_app) + assert str(excinfo.value).startswith('email_privacy_config must be of type' + ' EmailPrivacyConfig.') + def test_create_tenant(self, tenant_mgt_app): _, recorder = _instrument_tenant_mgt(tenant_mgt_app, 200, GET_TENANT_RESPONSE) - mfa_object = multi_factor_config_mgt.MultiFactorConfig( + mfa_object = MultiFactorConfig( provider_configs=[ - multi_factor_config_mgt.ProviderConfig( - state=multi_factor_config_mgt.ProviderConfig.State.ENABLED, - totp_provider_config=multi_factor_config_mgt.TOTPProviderConfig( + ProviderConfig( + state=ProviderConfig.State.ENABLED, + totp_provider_config=TOTPProviderConfig( adjacent_intervals=ADJACENT_INTERVALS ) ) ] ) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) tenant = tenant_mgt.create_tenant( display_name='My-Tenant', allow_password_sign_up=True, enable_email_link_sign_in=True, - multi_factor_config=mfa_object, app=tenant_mgt_app) + multi_factor_config=mfa_object, email_privacy_config=email_privacy_object, + app=tenant_mgt_app) _assert_tenant(tenant) self._assert_request(recorder, { @@ -286,6 +312,9 @@ def test_create_tenant(self, tenant_mgt_app): } ] }, + 'emailPrivacyConfig': { + 'enableImprovedEmailPrivacy': True + } }) def test_create_tenant_false_values(self, tenant_mgt_app): @@ -369,6 +398,14 @@ def test_invalid_multi_factor_configs(self, multi_factor_config, tenant_mgt_app) assert str(excinfo.value).startswith('multi_factor_config must be of type' ' MultiFactorConfig.') + @pytest.mark.parametrize('email_privacy_config', ['a', 1, True, {}, dict(), list(), tuple()]) + def test_invalid_email_privacy_configs(self, email_privacy_config, tenant_mgt_app): + with pytest.raises(ValueError) as excinfo: + tenant_mgt.update_tenant( + 'tenant-id', email_privacy_config=email_privacy_config, app=tenant_mgt_app) + assert str(excinfo.value).startswith('email_privacy_config must be of type' + ' EmailPrivacyConfig.') + def test_update_tenant_no_args(self, tenant_mgt_app): with pytest.raises(ValueError) as excinfo: tenant_mgt.update_tenant('tenant-id', app=tenant_mgt_app) @@ -376,20 +413,28 @@ def test_update_tenant_no_args(self, tenant_mgt_app): def test_update_tenant(self, tenant_mgt_app): _, recorder = _instrument_tenant_mgt(tenant_mgt_app, 200, GET_TENANT_RESPONSE) - mfa_object = multi_factor_config_mgt.MultiFactorConfig( + mfa_object = MultiFactorConfig( provider_configs=[ - multi_factor_config_mgt.ProviderConfig( - state=multi_factor_config_mgt.ProviderConfig.State.ENABLED, - totp_provider_config=multi_factor_config_mgt.TOTPProviderConfig( + ProviderConfig( + state=ProviderConfig.State.ENABLED, + totp_provider_config=TOTPProviderConfig( adjacent_intervals=ADJACENT_INTERVALS ) ) ] ) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) tenant = tenant_mgt.update_tenant( - 'tenant-id', display_name='My-Tenant', allow_password_sign_up=True, + tenant_id='tenant-id', + display_name='My-Tenant', + allow_password_sign_up=True, enable_email_link_sign_in=True, - multi_factor_config=mfa_object, app=tenant_mgt_app) + multi_factor_config=mfa_object, + email_privacy_config=email_privacy_object, + app=tenant_mgt_app + ) _assert_tenant(tenant) body = { @@ -405,17 +450,25 @@ def test_update_tenant(self, tenant_mgt_app): } } ] + }, + 'emailPrivacyConfig': { + 'enableImprovedEmailPrivacy': True, } } - mask = ['allowPasswordSignup', 'displayName', 'enableEmailLinkSignin', + mask = ['allowPasswordSignup', 'displayName', + 'emailPrivacyConfig.enableImprovedEmailPrivacy', + 'enableEmailLinkSignin', 'mfaConfig.providerConfigs'] self._assert_request(recorder, body, mask) def test_update_tenant_false_values(self, tenant_mgt_app): _, recorder = _instrument_tenant_mgt(tenant_mgt_app, 200, GET_TENANT_RESPONSE) tenant = tenant_mgt.update_tenant( - 'tenant-id', allow_password_sign_up=False, - enable_email_link_sign_in=False, app=tenant_mgt_app) + tenant_id='tenant-id', + allow_password_sign_up=False, + enable_email_link_sign_in=False, + app=tenant_mgt_app + ) _assert_tenant(tenant) body = { @@ -1065,18 +1118,22 @@ def test_custom_token_with_claims(self, tenant_aware_custom_token_app): custom_token, expected_claims=claims, tenant_id='test-tenant') def _assert_multi_factor_config(mfa_config): - assert isinstance(mfa_config, multi_factor_config_mgt.MultiFactorServerConfig) + assert isinstance(mfa_config, MultiFactorServerConfig) assert len(mfa_config.provider_configs) == 1 assert isinstance(mfa_config.provider_configs, list) for provider_config in mfa_config.provider_configs: - assert isinstance(provider_config, multi_factor_config_mgt.MultiFactorServerConfig.\ + assert isinstance(provider_config, MultiFactorServerConfig.\ ProviderServerConfig) assert provider_config.state == 'ENABLED' assert isinstance(provider_config.totp_provider_config, - multi_factor_config_mgt.MultiFactorServerConfig.ProviderServerConfig + MultiFactorServerConfig.ProviderServerConfig .TOTPProviderServerConfig) assert provider_config.totp_provider_config.adjacent_intervals == ADJACENT_INTERVALS +def _assert_email_privacy_config(email_privacy_config): + assert isinstance(email_privacy_config, EmailPrivacyServerConfig) + assert email_privacy_config.enable_improved_email_privacy is True + def _assert_tenant(tenant, tenant_id='tenant-id'): assert isinstance(tenant, tenant_mgt.Tenant) assert tenant.tenant_id == tenant_id @@ -1085,3 +1142,5 @@ def _assert_tenant(tenant, tenant_id='tenant-id'): assert tenant.enable_email_link_sign_in is True if tenant.multi_factor_config is not None: _assert_multi_factor_config(mfa_config=tenant.multi_factor_config) + if tenant.email_privacy_config is not None: + _assert_email_privacy_config(email_privacy_config=tenant.email_privacy_config) From aeacec520c2798f177bc3b593fb85c7ba14da2a8 Mon Sep 17 00:00:00 2001 From: Pragati Date: Thu, 21 Dec 2023 16:45:28 -0800 Subject: [PATCH 7/8] add integration tests --- integration/test_project_config_mgt.py | 33 ++++++++---------- integration/test_tenant_mgt.py | 47 ++++++++++++++++++-------- tests/test_project_config_mgt.py | 2 ++ 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/integration/test_project_config_mgt.py b/integration/test_project_config_mgt.py index 52b86841e..38003e003 100644 --- a/integration/test_project_config_mgt.py +++ b/integration/test_project_config_mgt.py @@ -23,23 +23,8 @@ from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig from firebase_admin.multi_factor_config_mgt import ProviderConfig from firebase_admin.multi_factor_config_mgt import TOTPProviderConfig - -ADJACENT_INTERVALS = 5 - -@pytest.fixture(scope='module') -def sample_mfa_config(): - mfa_config = { - 'providerConfigs': [ - { - 'state': 'ENABLED', - 'totpProviderConfig': { - 'adjacentIntervals': ADJACENT_INTERVALS - } - } - ] - } - return mfa_config - +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig def test_update_project_config(): mfa_object = MultiFactorConfig( @@ -52,14 +37,20 @@ def test_update_project_config(): ) ] ) - project_config = update_project_config(multi_factor_config=mfa_object) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) + project_config = update_project_config( + multi_factor_config=mfa_object, email_privacy_config=email_privacy_object) _assert_multi_factor_config(project_config.multi_factor_config) + _assert_email_privacy_config(project_config.email_privacy_config) def test_get_project(): project_config = get_project_config() assert isinstance(project_config, ProjectConfig) _assert_multi_factor_config(project_config.multi_factor_config) + _assert_email_privacy_config(project_config.email_privacy_config) def _assert_multi_factor_config(multi_factor_config): assert isinstance(multi_factor_config, MultiFactorServerConfig) @@ -72,4 +63,8 @@ def _assert_multi_factor_config(multi_factor_config): assert isinstance(provider_config.totp_provider_config, MultiFactorServerConfig.ProviderServerConfig .TOTPProviderServerConfig) - assert provider_config.totp_provider_config.adjacent_intervals == ADJACENT_INTERVALS + assert provider_config.totp_provider_config.adjacent_intervals == 5 + +def _assert_email_privacy_config(email_privacy_config): + assert isinstance(email_privacy_config, EmailPrivacyServerConfig) + assert email_privacy_config.enable_improved_email_privacy is True diff --git a/integration/test_tenant_mgt.py b/integration/test_tenant_mgt.py index 1766b2b1a..4dea01dd6 100644 --- a/integration/test_tenant_mgt.py +++ b/integration/test_tenant_mgt.py @@ -25,7 +25,12 @@ from firebase_admin import auth from firebase_admin import tenant_mgt -from firebase_admin import multi_factor_config_mgt +from firebase_admin.multi_factor_config_mgt import MultiFactorConfig +from firebase_admin.multi_factor_config_mgt import MultiFactorServerConfig +from firebase_admin.multi_factor_config_mgt import ProviderConfig +from firebase_admin.multi_factor_config_mgt import TOTPProviderConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyConfig +from firebase_admin.email_privacy_config_mgt import EmailPrivacyServerConfig from integration import test_auth @@ -36,35 +41,44 @@ @pytest.fixture(scope='module') def sample_tenant(): - mfa_object = multi_factor_config_mgt.MultiFactorConfig( - provider_configs=[multi_factor_config_mgt.ProviderConfig( - state=multi_factor_config_mgt.ProviderConfig.State.ENABLED, - totp_provider_config=multi_factor_config_mgt.TOTPProviderConfig( + mfa_object = MultiFactorConfig( + provider_configs=[ProviderConfig( + state=ProviderConfig.State.ENABLED, + totp_provider_config=TOTPProviderConfig( adjacent_intervals=5 ) )] ) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) tenant = tenant_mgt.create_tenant( display_name='admin-python-tenant', allow_password_sign_up=True, enable_email_link_sign_in=True, - multi_factor_config=mfa_object) + multi_factor_config=mfa_object, + email_privacy_config=email_privacy_object) yield tenant tenant_mgt.delete_tenant(tenant.tenant_id) def _assert_multi_factor_config(mfa_config): - assert isinstance(mfa_config, multi_factor_config_mgt.MultiFactorServerConfig) + assert isinstance(mfa_config, MultiFactorServerConfig) assert len(mfa_config.provider_configs) == 1 assert isinstance(mfa_config.provider_configs, list) for provider_config in mfa_config.provider_configs: - assert isinstance(provider_config, multi_factor_config_mgt.MultiFactorServerConfig.\ + assert isinstance(provider_config, MultiFactorServerConfig.\ ProviderServerConfig) assert provider_config.state == 'ENABLED' assert isinstance(provider_config.totp_provider_config, - multi_factor_config_mgt.MultiFactorServerConfig.ProviderServerConfig + MultiFactorServerConfig.ProviderServerConfig .TOTPProviderServerConfig) assert provider_config.totp_provider_config.adjacent_intervals == 5 + +def _assert_email_privacy_config(email_privacy_config): + assert isinstance(email_privacy_config, EmailPrivacyServerConfig) + assert email_privacy_config.enable_improved_email_privacy is True + @pytest.fixture(scope='module') def tenant_user(sample_tenant): client = tenant_mgt.auth_for_tenant(sample_tenant.tenant_id) @@ -82,6 +96,7 @@ def test_get_tenant(sample_tenant): assert tenant.allow_password_sign_up is True assert tenant.enable_email_link_sign_in is True _assert_multi_factor_config(tenant.multi_factor_config) + _assert_email_privacy_config(tenant.email_privacy_config) def test_list_tenants(sample_tenant): @@ -99,17 +114,20 @@ def test_list_tenants(sample_tenant): def test_update_tenant(): - mfa_object = multi_factor_config_mgt.MultiFactorConfig( - provider_configs=[multi_factor_config_mgt.ProviderConfig( - state=multi_factor_config_mgt.ProviderConfig.State.ENABLED, - totp_provider_config=multi_factor_config_mgt.TOTPProviderConfig( + mfa_object = MultiFactorConfig( + provider_configs=[ProviderConfig( + state=ProviderConfig.State.ENABLED, + totp_provider_config=TOTPProviderConfig( adjacent_intervals=5 ) )] ) + email_privacy_object = EmailPrivacyConfig( + enable_improved_email_privacy=True + ) tenant = tenant_mgt.create_tenant( display_name='py-update-test', allow_password_sign_up=True, enable_email_link_sign_in=True, - multi_factor_config=mfa_object) + multi_factor_config=mfa_object, email_privacy_config=email_privacy_object) try: tenant = tenant_mgt.update_tenant( tenant.tenant_id, display_name='updated-py-tenant', allow_password_sign_up=False, @@ -120,6 +138,7 @@ def test_update_tenant(): assert tenant.allow_password_sign_up is False assert tenant.enable_email_link_sign_in is False _assert_multi_factor_config(tenant.multi_factor_config) + _assert_email_privacy_config(tenant.email_privacy_config) finally: tenant_mgt.delete_tenant(tenant.tenant_id) diff --git a/tests/test_project_config_mgt.py b/tests/test_project_config_mgt.py index b4fa9b859..10882c4ab 100644 --- a/tests/test_project_config_mgt.py +++ b/tests/test_project_config_mgt.py @@ -210,3 +210,5 @@ def _assert_email_privacy_config(email_privacy_config): def _assert_project_config(project_config): if project_config.multi_factor_config is not None: _assert_multi_factor_config(project_config.multi_factor_config) + if project_config.email_privacy_config is not None: + _assert_email_privacy_config(project_config.email_privacy_config) From 8ee9ca81fb554024894e4cf6d7370dced68bcd85 Mon Sep 17 00:00:00 2001 From: Pragati Date: Thu, 21 Dec 2023 16:52:19 -0800 Subject: [PATCH 8/8] remove unused imports --- integration/test_project_config_mgt.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/integration/test_project_config_mgt.py b/integration/test_project_config_mgt.py index 38003e003..5b4a2f9d9 100644 --- a/integration/test_project_config_mgt.py +++ b/integration/test_project_config_mgt.py @@ -14,8 +14,6 @@ """Integration tests for firebase_admin.project_config_mgt module.""" -import pytest - from firebase_admin.project_config_mgt import ProjectConfig from firebase_admin.project_config_mgt import get_project_config from firebase_admin.project_config_mgt import update_project_config