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

Feature/face auth #169

Merged
merged 32 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
beea7bf
feat: face auth ui
ice-hades Aug 31, 2023
352d821
chore: added ffmpeg
ice-hades Sep 4, 2023
75e0f47
chore: face auth ui adjustments
ice-hades Sep 11, 2023
d268161
chore: emotions recognition ui
ice-hades Sep 12, 2023
246b88c
chore: adjusted cropped area
ice-hades Sep 15, 2023
1233170
chore: fixing ios build
ice-hades Sep 15, 2023
2ec33bd
feat: integrating be
ice-hades Sep 25, 2023
1773823
chore: get rid of emotions put request
ice-hades Sep 25, 2023
e913166
chore: keep track of active requests to process an emotion
ice-hades Sep 25, 2023
0a10723
chore: fix ios build
ice-hades Sep 25, 2023
9c1081b
chore: adjustment to api changes
ice-hades Sep 28, 2023
cb7be7f
chore: added keep awake during face auth
ice-hades Sep 28, 2023
74dbed4
chore: clean recoverable failed state on go back
ice-hades Sep 28, 2023
fbaa1a6
chore: added back button handler
ice-hades Sep 28, 2023
96351e1
chore: added emotions gifs
ice-hades Oct 2, 2023
701bc34
chore: applied a patch to deploy ios build to testflight
ice-hades Oct 2, 2023
7007c89
chore: updated emotions gifs
ice-hades Oct 2, 2023
72414e7
chore: show emotion preview
ice-hades Oct 2, 2023
659783e
chore: bumped expo camera
ice-hades Oct 3, 2023
e5e7646
chore: expo camera patch
ice-hades Oct 3, 2023
fa5e298
chore: revert gracefull recording stop
ice-hades Oct 3, 2023
93c7567
chore: fixing crash
ice-hades Oct 5, 2023
06a3818
chore: fixing crash
ice-hades Oct 9, 2023
1f2e840
chore: handling the back button gracefully
ice-hades Oct 9, 2023
27d5dbc
chore: feature flag to enable face recognition
ice-hades Oct 9, 2023
f0456d9
chore: new translations
ice-hades Oct 9, 2023
70d050d
chore: fixes after review
ice-hades Oct 9, 2023
981af94
chore: small fixes
ice-hades Oct 9, 2023
7739463
chore: changes after review
ice-hades Oct 10, 2023
d38eb29
chore: changes after review
ice-hades Oct 10, 2023
d15f44a
chore: fixed repeatableKYCSteps logic
ice-hades Oct 10, 2023
1207bd7
chore: small fix
ice-hades Oct 10, 2023
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
4 changes: 4 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ dependencies {
}

androidTestImplementation('com.wix:detox:+')

// For animated GIF support
implementation('com.facebook.fresco:fresco:2.5.0')
implementation 'com.facebook.fresco:animated-gif:2.5.0'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
4 changes: 3 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
buildscript {
ext {
buildToolsVersion = "33.0.0"
minSdkVersion = 23
minSdkVersion = 24
compileSdkVersion = 33
targetSdkVersion = 33
kotlinVersion = '1.8.10'
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
ndkVersion = "23.1.7779620"
androidXAnnotation = "1.5.0"
androidXBrowser = "1.4.0"
// https://github.com/arthenica/ffmpeg-kit/tree/main/react-native
ffmpegKitPackage = "video"
}
repositories {
google()
Expand Down
3 changes: 3 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ target 'ice' do
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
pod 'ReactNativeMoEngage', :path => '../node_modules/react-native-moengage'

# https://github.com/arthenica/ffmpeg-kit/tree/main/react-native#222-enabling-a-package-on-ios
pod 'ffmpeg-kit-react-native', :subspecs => ['video'], :podspec => '../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec'

pod 'Firebase', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
Expand Down
36 changes: 29 additions & 7 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ PODS:
- ExpoModulesCore
- ZXingObjC/OneD
- ZXingObjC/PDF417
- EXCamera (13.4.2):
- EXCamera (13.6.0):
- ExpoModulesCore
- EXFileSystem (15.4.2):
- ExpoModulesCore
- EXImageLoader (4.3.0):
- ExpoModulesCore
Expand All @@ -30,6 +32,8 @@ PODS:
- ExpoModulesCore
- GoogleSignIn (~> 7.0)
- React-Core
- ExpoKeepAwake (12.3.0):
- ExpoModulesCore
- ExpoModulesCore (1.5.7):
- RCT-Folly (= 2021.07.22.00)
- React-Core
Expand Down Expand Up @@ -58,6 +62,10 @@ PODS:
- FBSDKCoreKit (= 15.0.0)
- FBSDKShareKit (15.0.0):
- FBSDKCoreKit (= 15.0.0)
- ffmpeg-kit-ios-video (6.0)
- ffmpeg-kit-react-native/video (6.0.0):
- ffmpeg-kit-ios-video (= 6.0)
- React-Core
- Firebase (10.11.0):
- Firebase/Core (= 10.11.0)
- Firebase/AnalyticsWithoutAdIdSupport (10.11.0):
Expand Down Expand Up @@ -745,7 +753,7 @@ PODS:
- React-Core
- RNCClipboard (1.11.1):
- React-Core
- RNCMaskedView (0.2.8):
- RNCMaskedView (0.2.9):
- React-Core
- RNDeviceInfo (10.3.0):
- React-Core
Expand Down Expand Up @@ -794,7 +802,7 @@ PODS:
- React-Core
- RNReactNativeHapticFeedback (1.14.0):
- React-Core
- RNReanimated (3.3.0):
- RNReanimated (3.5.4):
- DoubleConversion
- FBLazyVector
- glog
Expand Down Expand Up @@ -862,13 +870,16 @@ DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXBarCodeScanner (from `../node_modules/expo-barcode-scanner/ios`)
- EXCamera (from `../node_modules/expo-camera/ios`)
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
- EXImageLoader (from `../node_modules/expo-image-loader/ios`)
- Expo (from `../node_modules/expo`)
- ExpoAdapterFBSDKNext (from `../node_modules/react-native-fbsdk-next/ios`)
- "ExpoAdapterGoogleSignIn (from `../node_modules/@react-native-google-signin/google-signin/expo/ios`)"
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- ffmpeg-kit-react-native/video (from `../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec`)
- Firebase
- Firebase/Messaging
- FirebaseCore
Expand Down Expand Up @@ -986,6 +997,7 @@ SPEC REPOS:
- FBSDKGamingServicesKit
- FBSDKLoginKit
- FBSDKShareKit
- ffmpeg-kit-ios-video
- Firebase
- FirebaseAnalytics
- FirebaseAppCheckInterop
Expand Down Expand Up @@ -1037,6 +1049,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-barcode-scanner/ios"
EXCamera:
:path: "../node_modules/expo-camera/ios"
EXFileSystem:
:path: "../node_modules/expo-file-system/ios"
EXImageLoader:
:path: "../node_modules/expo-image-loader/ios"
Expo:
Expand All @@ -1045,12 +1059,16 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-fbsdk-next/ios"
ExpoAdapterGoogleSignIn:
:path: "../node_modules/@react-native-google-signin/google-signin/expo/ios"
ExpoKeepAwake:
:path: "../node_modules/expo-keep-awake/ios"
ExpoModulesCore:
:path: "../node_modules/expo-modules-core"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
:path: "../node_modules/react-native/React/FBReactNativeSpec"
ffmpeg-kit-react-native:
:podspec: "../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
hermes-engine:
Expand Down Expand Up @@ -1214,11 +1232,13 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
EXBarCodeScanner: 44783bf0be375ab18a838dcfef29dd648397000a
EXCamera: 0fbfa338a3776af2722d626a3437abe33f708aad
EXCamera: 2dc2bd2828bca4e283018a0b5a84aec6639ff0b4
EXFileSystem: d7f59869885cfeab3ac771e2a8d0f5ed98cd3fdb
EXImageLoader: 34b214f9387e98f3c73989f15d8d5b399c9ab3f7
Expo: d5956de70d4076190861f6730b93e75478b6faf8
ExpoAdapterFBSDKNext: cb13ee1823c70383d17a82e7e2385053fa917d01
ExpoAdapterGoogleSignIn: b6e7ca3d25261737d31c274460b503ff1b6cb303
ExpoKeepAwake: be4cbd52d9b177cde0fd66daa1913afa3161fc1d
ExpoModulesCore: f8f3cac222bb0f574c77664d7e05817eaa97434b
FBAEMKit: d8312d8451ead46282adc7f3565ffc4965e3a4a7
FBLazyVector: 4cce221dd782d3ff7c4172167bba09d58af67ccb
Expand All @@ -1228,6 +1248,8 @@ SPEC CHECKSUMS:
FBSDKGamingServicesKit: e0766514d64d26a9f846e793c0a44bc4a236723b
FBSDKLoginKit: 11995469cd7da16fd4d5245e8d2ec61060479270
FBSDKShareKit: 9501792c3024580809f811a8a549868699d9bd32
ffmpeg-kit-ios-video: d3a8a535570063b717f88da68f9089e213aa21ba
ffmpeg-kit-react-native: a8aa8b5bed0a53ae573617e790984075bee2c716
Firebase: 31d9575c124839fb5abc0db6d39511cc1dab1b85
FirebaseAnalytics: 6c6bf99e8854475bf1fa342028841be8ecd236da
FirebaseAppCheckInterop: 5e12dc623d443dedffcde9c6f3ed41510125d8ef
Expand Down Expand Up @@ -1314,7 +1336,7 @@ SPEC CHECKSUMS:
RNBootSplash: 85f6b879c080e958afdb4c62ee04497b05fd7552
RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60
RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd
RNCMaskedView: bc0170f389056201c82a55e242e5d90070e18e5a
RNCMaskedView: 949696f25ec596bfc697fc88e6f95cf0c79669b6
RNDeviceInfo: 4701f0bf2a06b34654745053db0ce4cb0c53ada7
RNFBAnalytics: f13089c0af878ab74fba09f5e873c63e3f9de9c8
RNFBApp: fdbde65110240cd843e644270e974e9b455b0fc1
Expand All @@ -1329,7 +1351,7 @@ SPEC CHECKSUMS:
RNNotifee: 05692d7bb42b6c718a3906aeb8431c48ff2e8097
RNPermissions: dcdb7b99796bbeda6975a6e79ad519c41b251b1c
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
RNReanimated: 9f7068e43b9358a46a688d94a5a3adb258139457
RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87
RNScreens: 50ffe2fa2342eabb2d0afbe19f7c1af286bc7fb3
RNSentry: 9f0447b3ce13806f544903748de423259ead8552
RNSha256: 80bea5b2e7005f813f6438cb41e573b3d531146c
Expand All @@ -1345,6 +1367,6 @@ SPEC CHECKSUMS:
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb

PODFILE CHECKSUM: 8067a8dad58e9d795400789b2440f9bfc6719bb0
PODFILE CHECKSUM: 63d2fc0fc5753f2bd77dd80c3aa10b9a91ff85f5

COCOAPODS: 1.12.1
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@
"dayjs": "^1.11.6",
"expo": "^49.0.0",
"expo-barcode-scanner": "^12.5.3",
"expo-camera": "^13.4.2",
"expo-camera": "^13.6.0",
"exponential-backoff": "^3.1.0",
"ffmpeg-kit-react-native": "6.0.0",
"getstream": "^8.1.0",
"i18n-js": "^4.1.1",
"immer": "^9.0.16",
Expand Down Expand Up @@ -93,7 +94,7 @@
"react-native-pager-view": "^6.2.0",
"react-native-permissions": "^3.6.1",
"react-native-play-install-referrer": "^1.1.8",
"react-native-reanimated": "^3.3.0",
"react-native-reanimated": "^3.5.4",
"react-native-restart": "^0.0.27",
"react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.22.1",
Expand Down Expand Up @@ -162,10 +163,8 @@
"expo": {
"autolinking": {
"exclude": [
"expo-keep-awake",
"expo-application",
"expo-constants",
"expo-file-system",
"expo-font"
]
}
Expand Down
74 changes: 74 additions & 0 deletions patches/expo-camera+13.6.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Extra safety checks before calling stopRecording

diff --git a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/CameraViewModule.kt b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/CameraViewModule.kt
index 61240ed..5cf79d2 100644
--- a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/CameraViewModule.kt
+++ b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/CameraViewModule.kt
@@ -14,6 +14,7 @@ import expo.modules.kotlin.functions.Queues
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
import java.io.File
+import android.util.Log

class CameraViewModule : Module() {
override fun definition() = ModuleDefinition {
@@ -97,10 +98,18 @@ class CameraViewModule : Module() {
}.runOnQueue(Queues.MAIN)

AsyncFunction("stopRecording") { viewTag: Int ->
+ if (viewTag !is Int) {
+ return@AsyncFunction
+ }
val view = findView(viewTag)

- if (view.cameraView.isCameraOpened) {
- view.cameraView.stopRecording()
+ if (view != null && view.cameraView != null && view.cameraView.isCameraOpened) {
+ try {
+ view.cameraView.stopRecording()
+ } catch (e: Exception) {
+ // Handle or log the exception, depending on your needs
+ Log.e("StopRecording", "Error stopping recording: ${e.message}")
+ }
}
}.runOnQueue(Queues.MAIN)

diff --git a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
index b3591cd..a7c874a 100644
--- a/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
+++ b/node_modules/expo-camera/android/src/main/java/expo/modules/camera/ExpoCameraView.kt
@@ -7,6 +7,7 @@ import android.graphics.SurfaceTexture
import android.net.Uri
import android.os.Bundle
import android.view.View
+import android.util.Log
import com.google.android.cameraview.CameraView
import expo.modules.camera.CameraViewHelper.getCamcorderProfile
import expo.modules.camera.CameraViewHelper.getCorrectCameraRotation
@@ -314,13 +315,19 @@ class ExpoCameraView(
}
}

- override fun onHostPause() {
- if (!isPaused && cameraView.isCameraOpened) {
- faceDetector?.release()
- isPaused = true
- cameraView.stop()
- }
- }
+ override fun onHostPause() {
+ if (!isPaused && cameraView?.isCameraOpened == true) {
+ try {
+ faceDetector?.release()
+ cameraView?.stop()
+ } catch (e: Exception) {
+ Log.e("onHostPause", "Error occurred: ${e.message}")
+ } finally {
+ isPaused = true
+ }
+ }
+ }
+

override fun onHostDestroy() {
faceDetector?.release()
6 changes: 6 additions & 0 deletions src/api/auth/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// SPDX-License-Identifier: ice License 1.0

export type FaceAuthConfig = {
enabled: boolean;
};

export type AuthConfig =
| {
emailCodeAuthWhiteList: string[];
'face-auth': FaceAuthConfig;
}
| {
emailCodeAuthBlackList: string[];
'face-auth': FaceAuthConfig;
};
8 changes: 8 additions & 0 deletions src/api/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ export const is4xxApiError = (error: unknown) => {
);
};

export const is5xxApiError = (error: unknown) => {
return (
axios.isAxiosError(error) &&
error.response?.status &&
error.response.status >= 500
);
};

export const isNetworkError = (
error: unknown,
): error is AxiosError<{
Expand Down
7 changes: 7 additions & 0 deletions src/api/faceRecognition/deleteFaceAuthData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: ice License 1.0

import {del} from '@api/client';

export function deleteFaceAuthData(): Promise<void> {
return del<void>('/face-auth/');
}
34 changes: 34 additions & 0 deletions src/api/faceRecognition/emotionsAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: ice License 1.0

import {buildFormData, post} from '@api/client';
import {AuthEmotion} from '@api/faceRecognition/types';
import {getFilenameFromPath, normalizePictureUri} from '@utils/file';

type Response = {
result: boolean;
sessionEnded: boolean;
emotions: AuthEmotion[];
sessionId: string;
};

export function emotionsAuth({
userId,
sessionId,
pictureUris,
}: {
userId: string;
sessionId?: string | null;
pictureUris: string[];
}): Promise<Response> {
const formData = buildFormData({
image: pictureUris.map(pictureUri => ({
name: getFilenameFromPath(pictureUri),
type: 'image/jpeg',
uri: normalizePictureUri(pictureUri),
})),
});
return post<FormData, Response>(
`/face-auth/liveness/${userId}/${sessionId}`,
formData,
);
}
21 changes: 21 additions & 0 deletions src/api/faceRecognition/faceAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: ice License 1.0

import {buildFormData, post} from '@api/client';
import {getFilenameFromPath, normalizePictureUri} from '@utils/file';

export function faceAuth({
userId,
pictureUri,
}: {
userId: string;
pictureUri: string;
}): Promise<void> {
const formData = buildFormData({
image: {
name: getFilenameFromPath(pictureUri),
type: 'image/jpeg',
uri: normalizePictureUri(pictureUri),
},
});
return post<FormData, void>(`/face-auth/primary_photo/${userId}`, formData);
}
Loading
Loading