adding mfa login for admin

This commit is contained in:
Roland Osborne 2024-05-22 16:49:08 -07:00
parent f469aff9f6
commit 2b61d25726
3 changed files with 160 additions and 5 deletions

View File

@ -5,6 +5,8 @@ import { useAdmin } from './useAdmin.hook';
import Colors from 'constants/Colors';
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { tos } from 'constants/TermsOfService';
import { BlurView } from "@react-native-community/blur";
import { InputCode } from 'utils/InputCode';
export function Admin() {
@ -111,6 +113,47 @@ export function Admin() {
</TouchableOpacity>
</View>
</Modal>
<Modal
animationType="fade"
transparent={true}
visible={state.mfaModal}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={actions.dismissMFA}
>
<View>
<BlurView style={styles.mfaOverlay} blurType={Colors.overlay} blurAmount={2} reducedTransparencyFallbackColor="black" />
<View style={styles.mfaBase}>
<View style={styles.mfaContainer}>
<Text style={styles.mfaTitle}>{ state.strings.mfaTitle }</Text>
<Text style={styles.mfaDescription}>{ state.strings.mfaEnter }</Text>
<InputCode style={{ width: '100%' }} onChangeText={actions.setCode} />
<View style={styles.mfaError}>
{ state.mfaError == '403' && (
<Text style={styles.mfaErrorLabel}>{ state.strings.mfaError }</Text>
)}
{ state.mfaError == '429' && (
<Text style={styles.mfaErrorLabel}>{ state.strings.mfaDisabled }</Text>
)}
</View>
<View style={styles.mfaControl}>
<TouchableOpacity style={styles.mfaCancel} onPress={actions.dismissMFA}>
<Text style={styles.mfaCancelLabel}>{ state.strings.cancel }</Text>
</TouchableOpacity>
{ state.mfaCode != '' && (
<TouchableOpacity style={styles.mfaConfirm} onPress={actions.login}>
<Text style={styles.mfaConfirmLabel}>{ state.strings.mfaConfirm }</Text>
</TouchableOpacity>
)}
{ state.mfaCode == '' && (
<View style={styles.mfaDisabled}>
<Text style={styles.mfaDisabledLabel}>{ state.strings.mfaConfirm }</Text>
</View>
)}
</View>
</View>
</View>
</View>
</Modal>
</KeyboardAvoidingView>
);
}

View File

@ -15,6 +15,98 @@ export const styles = StyleSheet.create({
space: {
width: 32,
},
mfaOverlay: {
width: '100%',
height: '100%',
},
mfaError: {
width: '100%',
height: 24,
display: 'flex',
alignItems: 'center',
},
mfaErrorLabel: {
color: Colors.dangerText,
},
mfaControl: {
height: 32,
display: 'flex',
flexDirection: 'row',
width: '100%',
justifyContent: 'flex-end',
gap: 16,
},
mfaCancel: {
width: 72,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.cancelButton,
borderRadius: 4,
},
mfaCancelLabel: {
color: Colors.cancelButtonText,
},
mfaConfirm: {
width: 72,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.primaryButton,
borderRadius: 4,
},
mfaConfirmLabel: {
color: Colors.primaryButtonText,
},
mfaDisabled: {
width: 72,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Colors.disabledButton,
borderRadius: 4,
},
mfaDisabledLabel: {
color: Colors.disabledButtonText,
},
mfaBase: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
},
mfaContainer: {
backgroundColor: Colors.modalBase,
borderColor: Colors.modalBorder,
borderWidth: 1,
width: '80%',
maxWidth: 400,
display: 'flex',
gap: 8,
alignItems: 'center',
borderRadius: 8,
padding: 16,
},
mfaTitle: {
fontSize: 20,
color: Colors.descriptionText,
paddingBottom: 8,
},
mfaDescription: {
fontSize: 14,
color: Colors.descriptionText,
},
mfaCode: {
width: 400,
borderWidth: 1,
borderColor: '#333333',
width: '100%',
opacity: 0,
},
modalContainer: {
width: '100%',
height: '100%',

View File

@ -23,7 +23,9 @@ export function useAdmin() {
agree: false,
showTerms: false,
mfaModal: false,
mfaCode: '',
mfaError: null,
});
const updateState = (value) => {
@ -85,10 +87,22 @@ export function useAdmin() {
const unclaimed = await getNodeStatus(node);
if (unclaimed) {
await setNodeStatus(node, state.token);
}
const session = await setNodeAccess(node, state.token, state.mfaCode);
updateState({ server: node, busy: false });
navigate('/dashboard', { state: { server: node, token: session }});
}
try {
const session = await setNodeAccess(node, state.token, state.mfaCode);
updateState({ server: node, busy: false });
navigate('/dashboard', { state: { server: node, token: session }});
}
catch (err) {
if (err.message == '405' || err.message == '403' || err.message == '429') {
updateState({ mfaModal: true, mfaError: err.message });
}
else {
console.log(err.message);
updateState({ busy: false, showAlert: true });
throw new Error('login failed');
}
}
}
catch (err) {
console.log(err);
@ -96,7 +110,13 @@ export function useAdmin() {
throw new Error("access failed");
}
}
}
},
setCode: (mfaCode) => {
updateState({ mfaCode });
},
dismissMFA: () => {
updateState({ mfaModal: false });
},
};
return { state, actions };