@@ -20,7 +20,7 @@ import { MfaBackupCodeCreateScreen, MfaScreen, RemoveMfaPhoneCodeScreen, RemoveM
2020
2121export const MfaSection = ( ) => {
2222 const {
23- userSettings : { attributes } ,
23+ userSettings : { attributes, signUp } ,
2424 } = useEnvironment ( ) ;
2525 const { user } = useUser ( ) ;
2626 const [ actionValue , setActionValue ] = useState < string | null > ( null ) ;
@@ -34,12 +34,16 @@ export const MfaSection = () => {
3434
3535 const showTOTP = secondFactors . includes ( 'totp' ) && user . totpEnabled ;
3636 const showBackupCode = secondFactors . includes ( 'backup_code' ) && user . backupCodeEnabled ;
37+ const showPhoneCode = secondFactors . includes ( 'phone_code' ) ;
3738
3839 const mfaPhones = user . phoneNumbers
3940 . filter ( ph => ph . verification . status === 'verified' )
4041 . filter ( ph => ph . reservedForSecondFactor )
4142 . sort ( defaultFirst ) ;
4243
44+ const hideTOTPDeleteAction = Boolean ( signUp . mfa ?. required && mfaPhones . length === 0 ) ;
45+ const hidePhoneCodeDeleteAction = Boolean ( signUp . mfa ?. required && ! showTOTP && mfaPhones . length === 1 ) ;
46+
4347 return (
4448 < ProfileSection . Root
4549 title = { localizationKeys ( 'userProfile.start.mfaSection.title' ) }
@@ -68,7 +72,7 @@ export const MfaSection = () => {
6872 < Badge localizationKey = { localizationKeys ( 'badge__default' ) } />
6973 </ Flex >
7074
71- < MfaTOTPMenu />
75+ { ! hideTOTPDeleteAction && < MfaTOTPMenu /> }
7276 </ ProfileSection . Item >
7377
7478 < Action . Open value = 'remove-totp' >
@@ -79,7 +83,7 @@ export const MfaSection = () => {
7983 </ >
8084 ) }
8185
82- { secondFactors . includes ( 'phone_code' ) &&
86+ { showPhoneCode &&
8387 mfaPhones . map ( phone => {
8488 const isDefault = ! showTOTP && phone . defaultSecondFactor ;
8589 const phoneId = phone . id ;
@@ -102,7 +106,8 @@ export const MfaSection = () => {
102106
103107 < MfaPhoneCodeMenu
104108 phone = { phone }
105- showTOTP = { showTOTP }
109+ isDefault = { isDefault }
110+ hidePhoneCodeDeleteAction = { hidePhoneCodeDeleteAction }
106111 />
107112 </ ProfileSection . Item >
108113
@@ -153,30 +158,37 @@ export const MfaSection = () => {
153158
154159type MfaPhoneCodeMenuProps = {
155160 phone : PhoneNumberResource ;
156- showTOTP : boolean ;
161+ isDefault : boolean ;
162+ hidePhoneCodeDeleteAction : boolean ;
157163} ;
158164
159- const MfaPhoneCodeMenu = ( { phone, showTOTP } : MfaPhoneCodeMenuProps ) => {
165+ const MfaPhoneCodeMenu = ( { phone, isDefault , hidePhoneCodeDeleteAction } : MfaPhoneCodeMenuProps ) => {
160166 const { open } = useActionContext ( ) ;
161167 const card = useCardState ( ) ;
162168 const phoneId = phone . id ;
163169
164170 const actions = (
165171 [
166- ! showTOTP && ! phone . defaultSecondFactor
172+ ! isDefault
167173 ? {
168174 label : localizationKeys ( 'userProfile.start.mfaSection.phoneCode.actionLabel__setDefault' ) ,
169175 onClick : ( ) => phone . makeDefaultSecondFactor ( ) . catch ( err => handleError ( err , [ ] , card . setError ) ) ,
170176 }
171177 : null ,
172- {
173- label : localizationKeys ( 'userProfile.start.mfaSection.phoneCode.destructiveActionLabel' ) ,
174- isDestructive : true ,
175- onClick : ( ) => open ( `remove-${ phoneId } ` ) ,
176- } ,
178+ ! hidePhoneCodeDeleteAction
179+ ? {
180+ label : localizationKeys ( 'userProfile.start.mfaSection.phoneCode.destructiveActionLabel' ) ,
181+ isDestructive : true ,
182+ onClick : ( ) => open ( `remove-${ phoneId } ` ) ,
183+ }
184+ : null ,
177185 ] satisfies ( PropsOfComponent < typeof ThreeDotsMenu > [ 'actions' ] [ 0 ] | null ) [ ]
178186 ) . filter ( a => a !== null ) as PropsOfComponent < typeof ThreeDotsMenu > [ 'actions' ] ;
179187
188+ if ( actions . length === 0 ) {
189+ return null ;
190+ }
191+
180192 return < ThreeDotsMenu actions = { actions } /> ;
181193} ;
182194
@@ -216,6 +228,24 @@ type MfaAddMenuProps = ProfileSectionActionMenuItemProps & {
216228 onClick ?: ( ) => void ;
217229} ;
218230
231+ const strategiesMap = {
232+ phone_code : {
233+ icon : Mobile ,
234+ text : 'SMS code' ,
235+ key : 'phone_code' ,
236+ } ,
237+ totp : {
238+ icon : AuthApp ,
239+ text : 'Authenticator application' ,
240+ key : 'totp' ,
241+ } ,
242+ backup_code : {
243+ icon : DotCircle ,
244+ text : 'Backup code' ,
245+ key : 'backup_code' ,
246+ } ,
247+ } as const ;
248+
219249const MfaAddMenu = ( props : MfaAddMenuProps ) => {
220250 const { open } = useActionContext ( ) ;
221251 const { secondFactorsAvailableToAdd, onClick } = props ;
@@ -225,27 +255,7 @@ const MfaAddMenu = (props: MfaAddMenuProps) => {
225255 ( ) =>
226256 secondFactorsAvailableToAdd
227257 . map ( key => {
228- if ( key === 'phone_code' ) {
229- return {
230- icon : Mobile ,
231- text : 'SMS code' ,
232- key : 'phone_code' ,
233- } as const ;
234- } else if ( key === 'totp' ) {
235- return {
236- icon : AuthApp ,
237- text : 'Authenticator application' ,
238- key : 'totp' ,
239- } as const ;
240- } else if ( key === 'backup_code' ) {
241- return {
242- icon : DotCircle ,
243- text : 'Backup code' ,
244- key : 'backup_code' ,
245- } as const ;
246- }
247-
248- return null ;
258+ return strategiesMap [ key as keyof typeof strategiesMap ] || null ;
249259 } )
250260 . filter ( element => element !== null ) ,
251261 [ secondFactorsAvailableToAdd ] ,
@@ -260,21 +270,18 @@ const MfaAddMenu = (props: MfaAddMenuProps) => {
260270 triggerLocalizationKey = { localizationKeys ( 'userProfile.start.mfaSection.primaryButton' ) }
261271 onClick = { onClick }
262272 >
263- { strategies . map (
264- method =>
265- method && (
266- < ProfileSection . ActionMenuItem
267- key = { method . key }
268- id = { method . key }
269- localizationKey = { method . text }
270- leftIcon = { method . icon }
271- onClick = { ( ) => {
272- setSelectedStrategy ( method . key ) ;
273- open ( 'multi-factor' ) ;
274- } }
275- />
276- ) ,
277- ) }
273+ { strategies . map ( method => (
274+ < ProfileSection . ActionMenuItem
275+ key = { method . key }
276+ id = { method . key }
277+ localizationKey = { method . text }
278+ leftIcon = { method . icon }
279+ onClick = { ( ) => {
280+ setSelectedStrategy ( method . key ) ;
281+ open ( 'multi-factor' ) ;
282+ } }
283+ />
284+ ) ) }
278285 </ ProfileSection . ActionMenu >
279286 </ Action . Closed >
280287 ) }
0 commit comments