From b29bb2f84244400479e57e1d7d71df010e3c21fc Mon Sep 17 00:00:00 2001 From: Lauren Smith Date: Sun, 10 Dec 2023 19:33:29 -0500 Subject: [PATCH 1/3] Fixed removing email --- firebase_admin/_user_mgt.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/firebase_admin/_user_mgt.py b/firebase_admin/_user_mgt.py index c77c4d40d..782e82809 100644 --- a/firebase_admin/_user_mgt.py +++ b/firebase_admin/_user_mgt.py @@ -692,7 +692,7 @@ def update_user(self, uid, display_name=None, email=None, phone_number=None, """Updates an existing user account with the specified properties""" payload = { 'localId': _auth_utils.validate_uid(uid, required=True), - 'email': _auth_utils.validate_email(email), + 'email': _auth_utils.validate_email(email) if email is not DELETE_ATTRIBUTE else None, 'password': _auth_utils.validate_password(password), 'validSince': _auth_utils.validate_timestamp(valid_since, 'valid_since'), 'emailVerified': bool(email_verified) if email_verified is not None else None, @@ -720,6 +720,12 @@ def update_user(self, uid, display_name=None, email=None, phone_number=None, else: payload['phoneNumber'] = _auth_utils.validate_phone(phone_number) + if email is not None: + if email is DELETE_ATTRIBUTE: + remove_provider.append('email') + else: + payload['email'] = _auth_utils.validate_email(email) + if custom_claims is not None: if custom_claims is DELETE_ATTRIBUTE: custom_claims = {} From 97e6aaf6d1f182650282507f472790e71a364be8 Mon Sep 17 00:00:00 2001 From: Lauren Smith Date: Sun, 10 Dec 2023 19:33:53 -0500 Subject: [PATCH 2/3] Add unit testing --- tests/test_user_mgt.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/test_user_mgt.py b/tests/test_user_mgt.py index b590cca05..b67c47502 100644 --- a/tests/test_user_mgt.py +++ b/tests/test_user_mgt.py @@ -631,12 +631,13 @@ def test_update_user_delete_fields(self, user_mgt_app): 'testuser', display_name=auth.DELETE_ATTRIBUTE, photo_url=auth.DELETE_ATTRIBUTE, - phone_number=auth.DELETE_ATTRIBUTE) + phone_number=auth.DELETE_ATTRIBUTE, + email=auth.DELETE_ATTRIBUTE) request = json.loads(recorder[0].body.decode()) assert request == { 'localId' : 'testuser', 'deleteAttribute' : ['DISPLAY_NAME', 'PHOTO_URL'], - 'deleteProvider' : ['phone'], + 'deleteProvider' : ['phone', 'email'], } def test_update_user_error(self, user_mgt_app): @@ -681,6 +682,17 @@ def test_update_user_delete_provider_and_phone(self, user_mgt_app, arg): assert len(set(request['deleteProvider'])) == len(request['deleteProvider']) assert set(arg) - set(request['deleteProvider']) == set() + @pytest.mark.parametrize('arg', [['email', 'phone', 'google.com']]) + def test_update_user_delete_provider_and_email(self, user_mgt_app, arg): + user_mgt, recorder = _instrument_user_manager(user_mgt_app, 200, '{"localId":"testuser"}') + user_mgt.update_user('testuser', + email='yuvi@gmail.com', + providers_to_delete=arg) + request = json.loads(recorder[0].body.decode()) + assert 'email' in request['deleteProvider'] + assert len(set(request['deleteProvider'])) == len(request['deleteProvider']) + assert set(arg) - set(request['deleteProvider']) == set() + class TestSetCustomUserClaims: @pytest.mark.parametrize('arg', INVALID_STRINGS + ['a'*129]) From 49c8a70714c4d5c3bf82da79192e2f089695fdcc Mon Sep 17 00:00:00 2001 From: Adeline09 Date: Mon, 11 Dec 2023 05:12:08 -0500 Subject: [PATCH 3/3] Added field to allow default provider sign-up option --- .DS_Store | Bin 0 -> 10244 bytes firebase_admin/.DS_Store | Bin 0 -> 8196 bytes firebase_admin/tenant_mgt.py | 26 +++++++++++++++----- integration/.DS_Store | Bin 0 -> 6148 bytes integration/test_tenant_mgt.py | 10 +++++--- snippets/.DS_Store | Bin 0 -> 6148 bytes snippets/auth/.DS_Store | Bin 0 -> 6148 bytes snippets/auth/index.py | 3 ++- tests/.DS_Store | Bin 0 -> 8196 bytes tests/test_tenant_mgt.py | 42 ++++++++++++++++++++++++++------- tests/test_user_mgt.py | 2 +- 11 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 .DS_Store create mode 100644 firebase_admin/.DS_Store create mode 100644 integration/.DS_Store create mode 100644 snippets/.DS_Store create mode 100644 snippets/auth/.DS_Store create mode 100644 tests/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..867dd5775589e4a594058a3e5a56c4e3e84fc1e0 GIT binary patch literal 10244 zcmeHML2nyH6n>MYc#Yd;(XFs1OG(^ zkh5j6a$1_!Fkl!k3_NB)t`B)sDT}e}X{nYDG-?X~IgV~spkp7PF!@*(W7*SEK{2M@ zJ+K(c;w=W#aNN&JbI4*Wds=EZF%2gcduH(tg(>gA<&`XH68IXJT30k5x zx`|zTa{qpluG1W~sk!2bM%@#2SjynKhC2616=+1~Xop-1h*O;$3L$HdO(0$JQ`jH= z4Ys}?c4EIj);pdXM)UK(vawU+r(eog87pVqtK1j+mB@*@VaW;Z$g8RlUcIk7^-Y)W z*X*e!;YW_^^FRUICWp!0+pgaf`z6u!o1wy1^bIR(Wo!1#;o-uSh0FQH#f78G`NQ|G z%tL?oy`!V7HC=f7!;RXm*Y?F%iUDHrqC{u)_2c$yXwT%wZS2K!WWV(1_`7ZQXPJFD zcjoN5348MVg~_SO>FJBF%uLU|I{RA9zEF1>yRASz{gUuRQ1ZI`PAhPmm5$SJ{nl2* zA4C=RA+OozQ>Gid`Pq}M>OluKQ%^e7aMuIQeKp?N&Q8dqt%SZ^vnRqvAUtnfgl^;t zfBS9-?pGq-Uh#JXJnn(_wT`?MZt@_69Kvkf^PD>O*8Gx)BGKMK82lGm|rutp6WZ9}Oe4Z^7*W(_GF5!c| zL7TKo59u5FmcFB(=x6$k{-D2EhRw1!*d?~eK4Mqd$Lto{U=7w}F8e~`$NDe+^+8W8 z#Pu^@{9YySJ>j=tC&$RiV4(=X(?TdY&|DJf@L|$RGW15EPDtR4n4Jlk=Mgd=;L}1m z=8zfj%2UCTp;eqOFHspet3u_$9K+Uj;iX}tpqq5`oiR_qFqgm;O rj#o!B=+mb$+P(-O@jWe}p}g>a2ACr=us(2PX7>M&)Tj8r+5i6oYIA}B literal 0 HcmV?d00001 diff --git a/firebase_admin/.DS_Store b/firebase_admin/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c73e1e847911a8f4a54ed2f92e12e62f8a83956d GIT binary patch literal 8196 zcmeI1&2G~`6ov1URuu9>RaB`PB(GSosDxOtGgZ4_%>zKCk&__0%bwR@!2*fr zV+H5j8HJg6oNg*q!AxXd%b9cUoo{}eaYV$NE-#*o9E-?44%&kbPLaazc{Iw7yYmFr zKrd3sQWo+SpOZ%IbR!W+1QLNnAQ4Ce?g9Zkvsw0Ap8NLObWQ{kf&Y>K*M|%TZSL&K zT3tGD(k%e&E^ceVHTD6j$(+rdU0JJA__VtRg4pc?3Vf)TC?nLu5_#{%yR8fwG*{FsMf_6X zkAC2TZ!E^hBCh?pp=I`$$bSY+f$ObmCHCDTM)e5s7SP|=b|E=meFV)E?VRH?Ko%r_ ziF>41fP-bwM$z~5xW&`f));d1y|Djld5_pH^z$-Gp9FnX4=T2xys7U=&ph+!QMo`n zue8PN2ev%YUXlxxZ0}NI*0{2xg(Gf^>^b`Cm=}({zzciN_cBEs+_)goVq$b?Fbtw=c`!zl#;Kzzn+&7rb@%F-ADh`@Xk?ZSq@rf z5n1@!J*bAUoD5s<*X+UjXGAK&nhYw$iq2G0*m)XIVBa#sIh5?DG8z%R9Ow>pOoTeF zSaZ47c@|+ql7WvtA~Vkgbex-|8+8#aXH}r>M&@`-2U3A<54uULg-YhDN9G7Dxo&=aqKy>%l$?zJ-|8>az6Q|!Fy+#xO literal 0 HcmV?d00001 diff --git a/firebase_admin/tenant_mgt.py b/firebase_admin/tenant_mgt.py index 8c53e30a1..60e71f86d 100644 --- a/firebase_admin/tenant_mgt.py +++ b/firebase_admin/tenant_mgt.py @@ -91,7 +91,7 @@ def get_tenant(tenant_id, app=None): def create_tenant( - display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, app=None): + display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, allow_default_provider=None, app=None): """Creates a new tenant from the given options. Args: @@ -101,6 +101,8 @@ def create_tenant( provider (optional). 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. + allow_default_provider: A boolean indicating whether to enable or disable default provider + sign-in (optional). app: An App instance (optional). Returns: @@ -113,12 +115,12 @@ def create_tenant( tenant_mgt_service = _get_tenant_mgt_service(app) 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) + enable_email_link_sign_in=enable_email_link_sign_in, allow_default_provider=allow_default_provider) def update_tenant( tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - app=None): + allow_default_provider=None, app=None): """Updates an existing tenant with the given options. Args: @@ -128,6 +130,8 @@ def update_tenant( provider. 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. + allow_default_provider: A boolean indicating whether to enable or disable default provider + sign-in (optional). app: An App instance (optional). Returns: @@ -141,7 +145,7 @@ def update_tenant( tenant_mgt_service = _get_tenant_mgt_service(app) 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) + enable_email_link_sign_in=enable_email_link_sign_in, allow_default_provider=allow_default_provider) def delete_tenant(tenant_id, app=None): @@ -227,6 +231,10 @@ def allow_password_sign_up(self): @property def enable_email_link_sign_in(self): return self._data.get('enableEmailLinkSignin', False) + + @property + def allow_default_provider(self): + return self._data.get('allowDefaultProvider', False) class _TenantManagementService: @@ -272,7 +280,7 @@ def get_tenant(self, tenant_id): return Tenant(body) def create_tenant( - self, display_name, allow_password_sign_up=None, enable_email_link_sign_in=None): + self, display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, allow_default_provider=None): """Creates a new tenant from the given parameters.""" payload = {'displayName': _validate_display_name(display_name)} @@ -282,6 +290,9 @@ def create_tenant( if enable_email_link_sign_in is not None: payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( enable_email_link_sign_in, 'enableEmailLinkSignin') + if allow_default_provider is not None: + payload['allowDefaultProvider'] = _auth_utils.validate_boolean( + allow_default_provider, 'allowDefaultProvider') try: body = self.client.body('post', '/tenants', json=payload) @@ -292,7 +303,7 @@ def create_tenant( def update_tenant( self, tenant_id, display_name=None, allow_password_sign_up=None, - enable_email_link_sign_in=None): + enable_email_link_sign_in=None, allow_default_provider=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.') @@ -306,6 +317,9 @@ def update_tenant( if enable_email_link_sign_in is not None: payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( enable_email_link_sign_in, 'enableEmailLinkSignin') + if allow_default_provider is not None: + payload['allowDefaultProvider'] = _auth_utils.validate_boolean( + allow_default_provider, 'allowDefaultProvider') if not payload: raise ValueError('At least one parameter must be specified for update.') diff --git a/integration/.DS_Store b/integration/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..404a3182e45eaeb8b908524a00296ed1856979f8 GIT binary patch literal 6148 zcmeHK!A`*HL`XzEXiQ9c_CVqvRDuW3egHx#hyhAO4%~Y8S4{jqPx@wdLx!?? zG)8Bd-M8KDo6fv;yImr3oz?J)s6|9|6vo;Cs)+G*E<3gtdYV8dJ|^@`JsfRX?2NV! zQ@|AXZ3^(*ZOELR(46%AUEfZNY%nbb7{Q;1Yn1kf7+TEAr~qe#IiJ%KHP8Ag>#f3S zZbtX0Pb-`~#CYza!aGpBAq}FOmkQ@daYo4PDa2VwD;6#1_^NU|{ni6#u%tCK$fEJQ zSK>KQ-dJtctS{^wPhdjBm=|INbxb;|nPjwtmofNr)RC-2OYK2xIiqQm!&++2xr%)O z{R(=-y)*RoXeL>33_034;)uQrj`h$!50y{Wf}e}`63K$!KX<8~&9P$h8#tFJd_3cL z1gzzj4+Qj&4Qn=Az2VVnQ@|831vU!s_aQ-HOaqo4<n` zM_hq9PX&6a3tJ55>F7_wxHMqt(bLI=&4&wjc43F&^CT@eDm>iK(qexD3lZUDxbcL5i;L-`AI={+O0JMFqbe&)^3a#t;#;DWMtm`*f}D z$4zzVyqdWAex{SMsOo1CXxuZw&> z>fL>=Rh<+npBh4u!DF!O>tpJUkpM_rt}LqdwwC zkC)3p-rIZd^knq8JX89cSs4ku&BpFHyoB!vuGak}o~lx-F>+ilDT5+4JcU=3uj(T1 zqvpDP0eynrQ_4|WljdlR!B1OdoSEth^N+z*G+twzuQAZ|<`wV?cm=j7;J$LQyJgI$ zyaHZ<|62k6K7??_$YEpAd^*sWD*&*Kv@yi|XOTIf!^mM{5hE~RsX$8=?usES9r@7J zMGhN_mQKQ5K7@O+a5ofTo{srLQ%)kX=v%LVS723v9oy~k`TyeP`~ND*_q+mLfqzN? z(LRokhggz3TQ?TRXKe`o0B7U6#^MzPfjNp%%SZ7p+!*p92f)Z-V-Xpc|07^z@QqjC Hk1FsR^{k5O literal 0 HcmV?d00001 diff --git a/snippets/auth/.DS_Store b/snippets/auth/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1c6d511cb4368eacc2e7549333e9b8d1ac9d3368 GIT binary patch literal 6148 zcmeHKOHRW;41I)jEbaAb5vYk@mrg$4&^R6h2!A30KEXUudn zzjiVg%v58=i03|k8F&13HX*@4Fc1s`1Hr&g8Q__%QVcVO4hDjOVBnJh-5(O0V(Hjs zw5@~6N&w=3-6pj4vaB)5v2<)Ra)cr|l$b-sOAN{3>`(4jI<^^eIK+z&@h^WAFJfP3 z{$%cuGGpjqAQ(7hKx<#hNYDRk{xZEqzPW@727-bA%76@JH?t{M=V$A;b?RB0*lyWW r)UQ>8Li^+rz!%*|E^IK5C$;HUI<^@#i}qVMF)ji|NT^`o7Z`X4lVLqW literal 0 HcmV?d00001 diff --git a/snippets/auth/index.py b/snippets/auth/index.py index ed324e486..2932882f0 100644 --- a/snippets/auth/index.py +++ b/snippets/auth/index.py @@ -777,7 +777,8 @@ def create_tenant(): tenant = tenant_mgt.create_tenant( display_name='myTenant1', enable_email_link_sign_in=True, - allow_password_sign_up=True) + allow_password_sign_up=True, + allow_default_provider=True) print('Created tenant:', tenant.tenant_id) # [END create_tenant] diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..29915cdf7b9e0d989298f0f9b4f7735e9430188c GIT binary patch literal 8196 zcmeI1&u-H|5XNUq4;4Y8fYeq#jGOGNH$Gk!~SLPQ7H*d7kBi!{E@Tc_=XGe@uv z{zOw+Q-;qeEjqpJgb^?TM!*Od0VD7~5WsIXw}YPFeSg*VM!*O>NCNzPNU*U@gRQ-l zM+bIN0>JL$v@{%}4iKLt*fiMMTXBV^uO3`*b)m#?-W}Hy?hcy$$58jVPqF7 z6epv@FOlx#Qg3Z<1dKqJ0N3sVsoAGgHtP55PqQi?&8iW4@J;mr+v!#sj`)@z(-8Ik zu+{HRtKR^93R=mVfg#=tEadG#OWpl!c|GfRWt7tdN;zFc6<)Ozjv5LZe48N81udzf zZ^(2EttH~(cNOhu{lW_bZmj-ThFlB2%-wZgHAqN|XB!HTXCPaexj=2oj|niD9mkrB`C z46zkZS;thErhB7kY876)oY7EXD4@pk8_A6MHdHj5xo}xQ?2pEA~5^($HpU=-QVyLY