You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The loginDisplayNames mapping logic in the providers.map loop should be validated to ensure it handles cases where provider keys are missing or undefined in loginDisplayNames. This could lead to unexpected behavior or UI inconsistencies.
// get the provider display namesconstloginDisplayNames=configStore.store.config.loginMethodDisplayNames;// show the orconstshowOrDivider=providers.indexOf('native')>-1&&(providers.indexOf('ms')||providers.indexOf('google'));return(<><Snackbaropen={snackbar.open}anchorOrigin={{vertical: 'top',horizontal: 'right'}}autoHideDuration={6000}onClose={()=>{setSnackbar({open: false,message: '',color: 'success',});}}><Alertseverity={snackbar.color}sx={{width: '100%'}}>{snackbar.message}</Alert></Snackbar><StyledMain><StyledRow><StyledScroll><StyledContent><div><StyledLogoBox>{themeMap.isLogoUrl ? (<StyledLogosrc={themeMap.logo}/>) : THEME.logo ? (<StyledLogosrc={THEME.logo}/>) : null}<StyledLogoText>{themeMap.name
? themeMap.name
: THEME.name}</StyledLogoText></StyledLogoBox><Typographyvariant="h4">Welcome!</Typography><StyledInstructionsvariant="body1">{register
? 'Register below'
: 'Log in below'}</StyledInstructions></div>{!register&&(<StyledButtonGroupvariant="outlined">{configStore.store.config.providers.includes('native',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('Native');setSuccess('');setError('');}}selected={loginType==='Native'}>Native</StyledButtonGroupItem>)}{configStore.store.config.providers.includes('ldap',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('LDAP');setSuccess('');setError('');}}selected={loginType==='LDAP'}>LDAP</StyledButtonGroupItem>)}{configStore.store.config.providers.includes('linotp',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('LinOTP');setSuccess('');setError('');}}selected={loginType==='LinOTP'}>LinOTP</StyledButtonGroupItem>)}</StyledButtonGroup>)}{error&&<Alertcolor="error">{error}</Alert>}{success&&(<Alertcolor="success">{success}</Alert>)}<form><Stackspacing={2}>{providers.indexOf('native')>-1&&(<>{!showOTPCodeField&®ister&&(<><Controllername={'FIRST_NAME'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="First Name"variant="outlined"size="small"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'LAST_NAME'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Last Name"size="small"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'USERNAME'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Username"size="small"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'EMAIL'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Email"error={error.includes('is not a valid email address',)}helperText={error.includes('is not a valid email address',)&&'Please enter a valid email'}size="small"
variant="outlined"
fullWidthvalue={field.value
? field.value
: ''
}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'PHONE'}control={registerControl}rules={{required: false,}}render={({ field })=>{return(<TextFieldlabel="Phone Number"size="small"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'EXTENTION'}control={registerControl}rules={{required: false,}}render={({ field })=>{return(<TextFieldlabel="Phone Extention"size="small"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'COUNTRY_CODE'}control={registerControl}rules={{required: false,}}render={({ field })=>{return(<TextFieldlabel="Country Code"size="small"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'PASSWORD'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Password"error={error.includes('Passwords do not match',)||error.includes('Password must be at least 8 characters in length',)||error.includes('Password must have atleast one uppercase character',)||error.includes('Password must have atleast one lowercase character',)||error.includes('Password must have atleast one special character among [!,@,#,$,%,^,&,*]',)}helperText={error&&(error.includes('Password must be at least 8 characters in length',)||error.includes('Password must have atleast one uppercase character',)||error.includes('Password must have atleast one lowercase character',)||error.includes('Password must have atleast one special character among [!,@,#,$,%,^,&,*]',)||error.includes('Password must have atleast one special character among [!,@,#,$,%,^,&,*]',))
? error.includes('Passwords do no match',)
? 'Passwords do not match'
: 'Passwords must be at least 8 characters in length and contain one lowercase, one uppercase, one special character.'
: ''}size="small"variant="outlined"type="password"fullWidthvalue={
field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={
'PASSWORD_CONFIRMATION'
}control={
registerControl
}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Password Confirmation"size="small"error={error.includes('Passwords do not match',)||error.includes('Password must be at least 8 characters in length',)||error.includes('Password must have atleast one uppercase character',)||error.includes('Password must have atleast one lowercase character',)||error.includes('Password must have atleast one special character among [!,@,#,$,%,^,&,*]',)}helperText={error.includes('Passwords do not match',)&&
'Passwordsdonomatch'
}variant="outlined"
type="password"
fullWidthvalue={
field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><StyledGoBackBox><ButtonfullWidthvariant={'text'}
onClick={()=>setRegister(false,)}>GoBack</Button><ButtonfullWidthvariant={'contained'}onClick={
registerAccount
}>RegisterAccount</Button></StyledGoBackBox></>)}{!showOTPCodeField&&!register&&(<><Controllername={'USERNAME'}control={control}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Username"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'PASSWORD'}control={control}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Password"variant="outlined"type="password"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/></>)}{showOTPCodeField&&(<Controllername={'OTP_CONFIRM'}control={control}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="OTP Confirmation Code"variant="outlined"fullWidthvalue={field.value
? field.value
: ''}onChange={(e)=>field.onChange(e.target.value,)}/>);}}/>)}{!register&&(<><StyledRememberBox><Controllername={'REMEMBER_LOGIN'}control={control}rules={{required: false,}}render={({
field,})=>{return(<Checkboxlabel="Keep me logged in"checked={field.value}value={field.value
? field.value
: false}onChange={(e: React.ChangeEvent<HTMLInputElement>,)=>field.onChange(e.target.checked,)}/>);}}/><StyledButtonTextvariant="text"onClick={()=>setForgotPassword(true,)}>ForgotPassword</StyledButtonText></StyledRememberBox><ButtonfullWidthvariant={'contained'}onClick={login}type="submit"
>Loginwith{loginType}</Button><StyledRegisterNowBox>Don'thaveanaccount?{' '}<StyledButtonTextvariant="text"
onClick={()=>setRegister(true,)}>RegisterNow</StyledButtonText></StyledRegisterNowBox></>)}</>)}{!register&&(<>{showOrDivider&&(<><StyledDivider><StyledDividerBox>or</StyledDividerBox></StyledDivider></>)}{providers.map((provider,idx)=>{if(provider!='native'&&provider!='registration'&&provider!='ldap'&&provider!='linotp'){return(<StyledActionvariant="outlined"onClick={()=>{oauth(provider);}}fullWidthkey={idx}><StyledActionBox><StyledActionImagesrc={LoginImages[provider]
? LoginImages[provider]
: LoginImages['other']}/><StyledActionText>{loginDisplayNames[provider]
? loginDisplayNames[provider]
: provider}</StyledActionText></StyledActionBox></StyledAction>);}
The repeated conditional checks for provider values like 'native', 'ldap', and 'linotp' in multiple places could be refactored to improve maintainability and reduce redundancy.
// set initial selected login type from config.if(configStore.store.config.providers.includes('native')){setLoginType('Native');}elseif(configStore.store.config.providers.includes('ldap')){setLoginType('LDAP');}elseif(configStore.store.config.providers.includes('linOtp')){setLoginType('LinOTP');}},[]);/** * Allow the user to login */constlogin=handleSubmit(async(data: TypeUserLogin): Promise<TypeUserLogin>=>{// turn on loadingsetIsLoading(true);if(!data.USERNAME||!data.PASSWORD){setError('Username and Password is Required');return;}if(!showOTPCodeField){if(loginType==='Native'){awaitconfigStore.login(data.USERNAME,data.PASSWORD).then(()=>{// noop}).catch((error)=>{setError(error.message);}).finally(()=>{// turn off loadingsetIsLoading(false);});}if(loginType==='LDAP'){awaitconfigStore.loginLDAP(data.USERNAME,data.PASSWORD).then(()=>{// noop}).catch((error)=>{setError(error.message);}).finally(()=>{// turn off loadingsetIsLoading(false);});}if(loginType==='LinOTP'){awaitconfigStore.loginOTP(data.USERNAME,data.PASSWORD).then(()=>{// noopsetShowOTPCodeField(true);}).catch((error)=>{setError(error.message);}).finally(()=>{// turn off loadingsetIsLoading(false);});}}if(showOTPCodeField){awaitconfigStore.confirmOTP(data.OTP_CONFIRM).then(()=>{// noop}).catch((error)=>{setError(error.message);}).finally(()=>{// turn off loadingsetIsLoading(false);});setShowOTPCodeField(true);}},);/** * Allow the user to login */constregisterAccount=registerSubmit(async(data: TypeUserRegister): Promise<TypeUserRegister>=>{// turn on loadingsetIsLoading(true);if(!data.USERNAME||!data.PASSWORD||!data.PASSWORD_CONFIRMATION||!data.FIRST_NAME||!data.LAST_NAME||!data.EMAIL){setError('Username, password, password confirmation, email, first and last name are required',);setIsLoading(false);return;}if(data.PASSWORD!==data.PASSWORD_CONFIRMATION){setError('Passwords do not match');setIsLoading(false);return;}awaitconfigStore.register(`${data.FIRST_NAME}${data.LAST_NAME}`,data.USERNAME,data.EMAIL,data.PASSWORD,data.PHONE,data.EXTENTION,data.COUNTRY_CODE,).then((res)=>{if(res){setError('');setRegister(false);setSuccess('Account registration successful. Log in below.',);}}).catch((error)=>{setIsLoading(false);setError(error.message);}).finally(()=>{// turn off loadingsetIsLoading(false);});},);/** * Login with oauth * @param provider - provider to oauth with */constoauth=async(provider: string)=>{// turn on loadingsetIsLoading(true);awaitconfigStore.oauth(provider).then(()=>{// turn off loadingsetIsLoading(false);// noop// (handled by the configStore)setSnackbar({open: true,message: `Successfully logged in`,color: 'success',});}).catch((error)=>{// turn off loadingsetIsLoading(false);setError(error.message);setSnackbar({open: true,message: error.message,color: 'error',});});};constthemeMap=useMemo(()=>{consttheme=configStore.store.config['theme'];if(theme&&theme['THEME_MAP']){try{returnJSON.parse(theme['THEME_MAP']asstring);}catch{return{};}}return{};},[Object.keys(configStore.store.config).length]);// get the path the user is coming fromconstpath=(location.stateas{from: Location})?.from?.pathname||'/';// navigate if already logged inif(configStore.store.status==='SUCCESS'){return<Navigateto={path}replace/>;}// get the proviersconstproviders=[...configStore.store.config.providers];// get the provider display namesconstloginDisplayNames=configStore.store.config.loginMethodDisplayNames;// show the orconstshowOrDivider=providers.indexOf('native')>-1&&(providers.indexOf('ms')||providers.indexOf('google'));return(<><Snackbaropen={snackbar.open}anchorOrigin={{vertical: 'top',horizontal: 'right'}}autoHideDuration={6000}onClose={()=>{setSnackbar({open: false,message: '',color: 'success',});}}><Alertseverity={snackbar.color}sx={{width: '100%'}}>{snackbar.message}</Alert></Snackbar><StyledMain><StyledRow><StyledScroll><StyledContent><div><StyledLogoBox>{themeMap.isLogoUrl ? (<StyledLogosrc={themeMap.logo}/>) : THEME.logo ? (<StyledLogosrc={THEME.logo}/>) : null}<StyledLogoText>{themeMap.name
? themeMap.name
: THEME.name}</StyledLogoText></StyledLogoBox><Typographyvariant="h4">Welcome!</Typography><StyledInstructionsvariant="body1">{register
? 'Register below'
: 'Log in below'}</StyledInstructions></div>{!register&&(<StyledButtonGroupvariant="outlined">{configStore.store.config.providers.includes('native',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('Native');setSuccess('');setError('');}}selected={loginType==='Native'}>Native</StyledButtonGroupItem>)}{configStore.store.config.providers.includes('ldap',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('LDAP');setSuccess('');setError('');}}selected={loginType==='LDAP'}>LDAP</StyledButtonGroupItem>)}{configStore.store.config.providers.includes('linotp',)&&(<StyledButtonGroupItemonClick={()=>{setLoginType('LinOTP');setSuccess('');setError('');}}selected={loginType==='LinOTP'}>LinOTP</StyledButtonGroupItem>)}</StyledButtonGroup>)}{error&&<Alertcolor="error">{error}</Alert>}{success&&(<Alertcolor="success">{success}</Alert>)}<form><Stackspacing={2}>{providers.indexOf('native')>-1&&(<>{!showOTPCodeField&®ister&&(<><Controllername={'FIRST_NAME'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="First Name"variant="outlined"size="small"fullWidthvalue={field.value
? field.value
: ''}onChange={(e,)=>field.onChange(e.target.value,)}/>);}}/><Controllername={'LAST_NAME'}control={registerControl}rules={{required: true,}}render={({ field })=>{return(<TextFieldlabel="Last ...
Why: Initializing the loginMethodDisplayNames object with all required provider keys ensures that display names are always defined, preventing potential runtime issues. This is a critical improvement for maintaining consistent and error-free UI behavior.
High
Add error handling for oauth
Add a fallback mechanism or error handling for the oauth(provider) function to ensure it gracefully handles invalid or unsupported providers.
Why: Adding error handling for the oauth(provider) function is a good practice to ensure the application gracefully handles invalid or unsupported providers. However, the suggestion could be improved by specifying how unsupported providers should be handled beyond logging an error.
Medium
Possible issue
Add validation for missing provider keys
Ensure that the loginDisplayNames object is properly validated to handle cases where a provider key might be missing or undefined, to avoid potential runtime errors.
Why: The suggestion improves robustness by ensuring that missing provider keys in the loginDisplayNames object do not cause runtime errors. The use of optional chaining and nullish coalescing is a concise and effective way to handle this scenario.
Medium
Validate image source for providers
Validate that the LoginImages object contains all expected provider keys to prevent undefined image sources during runtime.
Why: This suggestion enhances the code by validating the LoginImages object to avoid undefined image sources, which could lead to broken UI elements. The use of optional chaining and nullish coalescing ensures a fallback image is always provided.
Ensure that the loginDisplayNames object is properly validated to avoid potential runtime errors when accessing undefined properties for providers not listed in the configuration.
Why: The suggestion improves robustness by using optional chaining and nullish coalescing to handle undefined properties in loginDisplayNames. This prevents potential runtime errors when accessing properties for providers not listed in the configuration.
8
General
Validate provider keys in LoginImages
Validate that the LoginImages object contains all expected provider keys to prevent fallback to the 'other' image for valid providers.
Why: The suggestion enhances code reliability by using optional chaining and nullish coalescing to ensure that LoginImages gracefully handles missing provider keys, avoiding fallback to the 'other' image unnecessarily.
8
Prevent duplicate or invalid providers
Add a check to ensure that the providers array does not contain duplicate or invalid entries to prevent redundant or erroneous UI elements.
Why: This suggestion improves the UI logic by filtering out duplicate or invalid providers from the providers array. It ensures that only unique and valid providers are rendered, reducing redundancy and potential errors.
7
Initialize loginMethodDisplayNames with defaults
Ensure that the loginMethodDisplayNames object is initialized with meaningful default values to avoid potential issues when accessed before being populated.
Why: Initializing loginMethodDisplayNames with meaningful default values improves code safety by ensuring that the object has valid entries before being populated. However, the impact is moderate as it primarily addresses a potential edge case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adding in loginMethodDisplayNames to properly display other login names on login buttons and mapping through list of providers to display each one.