Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication screen #58

Merged
merged 22 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />

<!-- TODO android:roundIcon="@mipmap/ic_launcher_round" -->
<application
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.reactlibrary.securekeystore.RNSecureKeyStorePackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
Expand Down
2 changes: 2 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
rootProject.name = 'GaloyApp'
include ':react-native-secure-key-store'
project(':react-native-secure-key-store').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-secure-key-store/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
30 changes: 30 additions & 0 deletions app/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"lastName": "Last Name",
"username": "Username",
"logout": "Log Out",
"loggedOut": "You have been logged out.",
"email": "Email",
"sats": "sats",
"to": "To",
Expand All @@ -22,6 +23,7 @@
"activateWallet": "Activate Wallet",
"later": "Later",
"notification": "Notification",
"security": "Security",
"share": "Share",
"shareLightning": "Share Lightning Invoice",
"shareBitcoin": "Share Bitcoin Address",
Expand Down Expand Up @@ -93,10 +95,38 @@
"success": "%{input} is now your username!",
"letterAndNumber": "Only lowercase letter, number and underscore (_) are accepted"
},
"SecurityScreen": {
"biometricTitle": "Biometric",
"biometricSubtitle": "Enable biometric authentication",
"biometricDescription": "Unlock with fingerprint or facial recognition.",
"pinTitle": "PIN Code",
"pinSubtitle": "Enable PIN",
"pinDescription": "PIN is used as the backup authentication method for biometric authentication.",
"setPin": "Set PIN",
"biometryNotAvailable": "Biometric sensor is not available.",
"biometryNotEnrolled": "Please register at least one biometric sensor in order to use biometric based authentication."
},
"GetStartedScreen": {
"headline": "Wallet powered by Galoy",
"getStarted": "Get Started"
},
"AuthenticationScreen": {
"unlock": "Unlock",
"authenticationDescription": "Authenticate to continue",
"setUp": "Set up Biometric Authentication",
"setUpAuthenticationDescription": "Use biometric to authenticate",
"skip": "Skip",
"usePin": "Use PIN"
},
"PinScreen": {
"setPin": "Set your PIN code",
"setPinFailedMatch": "Pins didn't match - Set your PIN code",
"verifyPin": "Verify your PIN code",
"storePinFailed": "Unable to store your pin.",
"attemptsRemaining": "Incorrect PIN. %{attemptsRemaining} attempts remaining.",
"oneAttemptRemaining": "Incorrect PIN. 1 attempt remaining.",
"tooManyAttempts": "Too many failed attempts. Logging out."
},
"WelcomeFirstScreen": {
"care": "Why should I care?",
"bank": "Bitcoin is designed to let you store, send and receive money, without relying on a bank or credit card",
Expand Down
32 changes: 31 additions & 1 deletion app/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@
"lastName": "Apellido",
"later": "Más tarde",
"logout": "cerrar sesion",
"loggedOut": "Usted ha sido desconectado.",
"next": "Próximo",
"note": "Nota ",
"notification": "Notificación",
"ok": "OK",
"phoneNumber": "Número de teléfono",
"sats": "Satoshis",
"security": "Seguridad",
"send": "Enviar",
"setAnAmount": "Establecer una cantidad",
"share": "Compartir",
Expand Down Expand Up @@ -514,6 +516,23 @@
"getStarted": "Empezar",
"headline": "El banco con dinero sólido"
},
"AuthenticationScreen": {
"unlock": "Desbloquear",
"authenticationDescription": "Autentica para continuar",
"setUp": "Configurar la Autenticación Biométrica",
"setUpAuthenticationDescription": "Utilice datos biométricos para autenticarse",
"skip": "Saltar",
"usePin": "Usar PIN"
},
"PinScreen": {
"setPin": "Establezca su código PIN",
"setPinFailedMatch": "Los pines no coinciden: establezca su código PIN",
"verifyPin": "Verifica tu código PIN",
"storePinFailed": "No se puede guardar su pin.",
"attemptsRemaining": "PIN incorrecto. %{attemptsRemaining} intentos restantes.",
"oneAttemptRemaining": "PIN incorrecto. Queda 1 intento.",
"tooManyAttempts": "Demasiados intentos fallidos. Saliendo de tu cuenta."
},
"MapScreen": {
"title": "mapa"
},
Expand Down Expand Up @@ -600,6 +619,17 @@
"confirmTitle": "establece tu nombre de usario",
"usernameToUse": "Que nombre de usuario quieres usar?"
},
"SecurityScreen": {
"biometricTitle": "Biométrica",
"biometricSubtitle": "Habilitar la autenticación biométrica",
"biometricDescription": "Desbloqueo con huella dactilar o reconocimiento facial.",
"pinTitle": "Código PIN",
"pinSubtitle": "Habilitar PIN",
"pinDescription": "El PIN se utiliza como método de autenticación de respaldo para la autenticación biométrica.",
"setPin": "Establecer PIN",
"biometryNotAvailable": "El sensor biométrico no está disponible.",
"biometryNotEnrolled": "Registre al menos un sensor biométrico para utilizar la autenticación basada en datos biométricos."
},
"WelcomeFirstScreen": {
"bank": "Bitcoin está diseñado para permitirle almacenar, enviar y recibir dinero, sin depender de un banco o tarjeta de crédito.",
"before": "Antes de Bitcoin, la gente tenía que depender de bancos o proveedores de tarjetas de crédito para gastar, enviar y recibir dinero.",
Expand All @@ -616,4 +646,4 @@
"need6Digits": "El código debe tener 6 didgits",
"placeholder": "Código de 6 dígitos"
}
}
}
30 changes: 29 additions & 1 deletion app/navigation/root-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import {
walletIsActive,
} from "../graphql/query"
import { translate } from "../i18n"
import {
AuthenticationScreen,
AuthenticationCheckScreen,
} from "../screens/authentication-screen"
import { PinScreen } from "../screens/authentication-screen/pin-screen"
import { ContactsDetailScreen } from "../screens/contacts-detail-screen"
import { ContactsScreen } from "../screens/contacts-screen"
import { DebugScreen } from "../screens/debug-screen"
Expand All @@ -39,6 +44,7 @@ import { ReceiveBitcoinScreen } from "../screens/receive-bitcoin-screen"
import { ScanningQRCodeScreen, SendBitcoinScreen } from "../screens/send-bitcoin-screen"
import { SettingsScreen, UsernameScreen } from "../screens/settings-screen"
import { LanguageScreen } from "../screens/settings-screen/language-screen"
import { SecurityScreen } from "../screens/settings-screen/security-screen"
import { TransactionDetailScreen } from "../screens/transaction-detail-screen"
import { TransactionHistoryScreenDataInjected } from "../screens/transaction-screen/transaction-screen"
import { WelcomeFirstScreen } from "../screens/welcome-screens"
Expand Down Expand Up @@ -260,7 +266,7 @@ export const RootStack = () => {
return (
<RootNavigator.Navigator
screenOptions={{ gestureEnabled: false }}
initialRouteName={token.has() ? "Primary" : "getStarted"}
initialRouteName={token.has() ? "authenticationCheck" : "getStarted"}
>
<RootNavigator.Screen
name="getStarted"
Expand All @@ -276,6 +282,21 @@ export const RootStack = () => {
component={WelcomeFirstScreen}
options={{ headerShown: false }}
/>
<RootNavigator.Screen
name="authenticationCheck"
component={AuthenticationCheckScreen}
options={{ headerShown: false, animationEnabled: false }}
/>
<RootNavigator.Screen
name="authentication"
component={AuthenticationScreen}
options={{ headerShown: false, animationEnabled: false }}
/>
<RootNavigator.Screen
name="pin"
component={PinScreen}
options={{ headerShown: false }}
/>
<RootNavigator.Screen
name="Primary"
component={PrimaryNavigator}
Expand Down Expand Up @@ -335,6 +356,13 @@ export const RootStack = () => {
title: "Language preference",
})}
/>
<RootNavigator.Screen
name="security"
component={SecurityScreen}
options={() => ({
title: "Security",
})}
/>
<RootNavigator.Screen name="Profile" component={DebugScreen} />
<RootNavigator.Screen
name="sectionCompleted"
Expand Down
64 changes: 64 additions & 0 deletions app/screens/authentication-screen/authentication-check-screen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as React from "react"
import { useEffect } from "react"
import { Image } from "react-native"
import EStyleSheet from "react-native-extended-stylesheet"

import { Screen } from "../../components/screen"
import { palette } from "../../theme/palette"
import KeyStoreWrapper from "../../utils/storage/secureStorage"
import BiometricWrapper from "../../utils/biometricAuthentication"
import type { ScreenType } from "../../types/screen"
import { AuthenticationScreenPurpose, PinScreenPurpose } from "../../utils/enum"

// eslint-disable-next-line @typescript-eslint/no-var-requires
const BitcoinBeachLogo = require("../get-started-screen/bitcoinBeach3.png")

const styles = EStyleSheet.create({
Logo: {
marginTop: 24,
maxHeight: "50%",
maxWidth: "50%",
},

container: {
alignItems: "center",
flex: 1,
width: "100%",
},
})

type Props = {
navigation: any
}

export const AuthenticationCheckScreen: ScreenType = ({ navigation }: Props) => {
useEffect(() => {
;(async () => {
const isPinEnabled = await KeyStoreWrapper.getIsPinEnabled()

if (
(await BiometricWrapper.isSensorAvailable()) &&
(await KeyStoreWrapper.getIsBiometricsEnabled())
) {
navigation.replace("authentication", {
screenPurpose: AuthenticationScreenPurpose.Authenticate,
isPinEnabled,
})
} else if (isPinEnabled) {
navigation.replace("pin", { screenPurpose: PinScreenPurpose.AuthenticatePin })
} else {
navigation.replace("Primary")
}
})()
}, [])

return (
<Screen
style={styles.container}
backgroundColor={palette.lightBlue}
statusBar="light-content"
>
<Image style={styles.Logo} source={BitcoinBeachLogo} resizeMode="contain" />
</Screen>
)
}
Loading