diff --git a/app/mobile/src/access/login/Login.jsx b/app/mobile/src/access/login/Login.jsx index 6aca9deb..f46b3055 100644 --- a/app/mobile/src/access/login/Login.jsx +++ b/app/mobile/src/access/login/Login.jsx @@ -5,6 +5,7 @@ import { useLogin } from './useLogin.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"; export function Login() { @@ -124,6 +125,24 @@ export function Login() { + + + + + + Multi-Factor Authentication + Enter your verification code + + + + + ); } diff --git a/app/mobile/src/access/login/Login.styled.js b/app/mobile/src/access/login/Login.styled.js index d684646d..34401765 100644 --- a/app/mobile/src/access/login/Login.styled.js +++ b/app/mobile/src/access/login/Login.styled.js @@ -22,6 +22,38 @@ export const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', }, + mfaOverlay: { + width: '100%', + height: '100%', + }, + 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: 16, + alignItems: 'center', + borderRadius: 8, + padding: 16, + }, + mfaTitle: { + fontSize: 20, + }, + mfaDescription: { + fontSize: 16, + }, tos: { display: 'flex', flexDirection: 'column', diff --git a/app/mobile/src/access/login/useLogin.hook.js b/app/mobile/src/access/login/useLogin.hook.js index 9f93d14a..cf4697b2 100644 --- a/app/mobile/src/access/login/useLogin.hook.js +++ b/app/mobile/src/access/login/useLogin.hook.js @@ -18,6 +18,9 @@ export function useLogin() { showPassword: false, agree: false, showTerms: false, + mfaModal: false, + mfaCode: null, + mfaError: null, }); const updateState = (value) => { @@ -77,15 +80,22 @@ export function useLogin() { await app.actions.login(state.login.trim(), state.password); } catch (err) { - console.log(err); - updateState({ busy: false, showAlert: true }); - throw new Error('login failed'); + if (err.message == '405' || err.message == '403' || err.message == '429') { + updateState({ mfaModal: true, mfaError: err.message, mfaCode: '' }); + } + else { + console.log(err.message); + updateState({ busy: false, showAlert: true }); + throw new Error('login failed'); + } } updateState({ busy: false }); } - } + }, + dismissMFA: () => { + updateState({ mfaModal: false }); + }, }; return { state, actions }; } - diff --git a/app/mobile/src/api/fetchUtil.js b/app/mobile/src/api/fetchUtil.js index a5ed506d..dc230514 100644 --- a/app/mobile/src/api/fetchUtil.js +++ b/app/mobile/src/api/fetchUtil.js @@ -8,7 +8,7 @@ export function createWebsocket(url) { export function checkResponse(response) { if(response.status >= 400 && response.status < 600) { - throw new Error(response.url + " failed"); + throw new Error(response.status); } }