mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-07 20:53:54 -05:00
[INJIMOB-1192] onboarding of new issuer is affecting the existing issuers (#1476)
* [INJIMOB-1192] : use wellknown response instead of mimoto issuer config. -- Remove hardcoding for sunbird issuer in vc activation and verification flow. -- Render idType from wellknown response -- Remove UIN/VID from default add-on fields Signed-off-by: Swati Goel <meet2swati@gmail.com> * [INJIMOB-1192] : fix propType and some refactoring Signed-off-by: Swati Goel <meet2swati@gmail.com> * [INJIMOB-1192] : add credentialType in VcMetadata Signed-off-by: Swati Goel <meet2swati@gmail.com> * [INJIMOB-1192] fix vc download via issuer flow due to credentialType mismatch Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] rename supported list of credential type in issuers model Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] display id type in history based on wellknown for issuers VC Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] fix id type not shown for VC activation Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] remove unused credentialType field from VCMetaData Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] set default idType for logging activity Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] move vc item machine events into model Events should not be exported to other packages for direct use so that Xstate's createModel() can decorate the function appropriately Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] show verify banner id type from wellknown Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] refactor duplication and unused code Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] remove unused displayId in metadata Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] revert the dimensions of camera scanner to old values to support face liveness verification Co-authored-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-1192] remove unused code & debug logs Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1192] fix failing test cases Co-authored-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-1192] remove unused translations Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --------- Signed-off-by: Swati Goel <meet2swati@gmail.com> Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Co-authored-by: Swati Goel <meet2swati@gmail.com> Co-authored-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
339e08c462
commit
003cc156c2
36
.talismanrc
36
.talismanrc
@@ -2,7 +2,7 @@ fileignoreconfig:
|
||||
- filename: package.json
|
||||
checksum: 5b4fcb5ddc7cc96cc2d1733b544d56ea66e88cdab995a1052fbf9ac0e9c2dc21
|
||||
- filename: package-lock.json
|
||||
checksum: 50254c7e3e84d59dceb77cde95ce71cb5d0625cb5ec84971a28b6fc4f95db7f1
|
||||
checksum: 98f4ef19f06521bac3ea3033d82810203214bf55b0469790a1d8acc20933c581
|
||||
- filename: lib/jsonld-signatures/suites/ed255192018/ed25519.ts
|
||||
checksum: 493b6e31144116cb612c24d98b97d8adcad5609c0a52c865a6847ced0a0ddc3a
|
||||
- filename: components/PasscodeVerify.tsx
|
||||
@@ -38,7 +38,7 @@ fileignoreconfig:
|
||||
- filename: screens/Home/MyVcs/GetIdInputModal.tsx
|
||||
checksum: 5c736ed79a372d0ffa7c02eb33d0dc06edbbb08d120978ff287f5f06cd6c7746
|
||||
- filename: shared/openId4VCI/Utils.ts
|
||||
checksum: f8b53de9c07074dc3a73f9443ba140c7e86300b4a2beac1a84bfccafb55ecd6a
|
||||
checksum: ee4db1768be8d51fac0eb876a7b16fd2ab1806abcc711f01056f672003d11f31
|
||||
- filename: shared/cryptoutil/cryptoUtil.ts
|
||||
checksum: 2efef1baca1eee0da60420c8d966a6d58589bc3ac74169ab1cdc19423b630dba
|
||||
- filename: shared/telemetry/TelemetryConstants.js
|
||||
@@ -63,8 +63,10 @@ fileignoreconfig:
|
||||
checksum: 736b5a7ddb86bd4376229ce198dbf8a663e7ac89fc3311bd4f19afd4a2b36ffd
|
||||
- filename: assets/Finger_Print_Icon.svg
|
||||
checksum: 776d4fe4fc4b54d185ccf97daf0511b9fe2c0e0f7c1a809047020e5e8a100db6
|
||||
- filename: screens/MainLayout.tsx
|
||||
checksum: 53ead79279c9609e42a8993db1a66bdb4649e1ae3b909d462b45b00c507c416e
|
||||
- filename: android/app/build.gradle
|
||||
checksum: 9f9cdcd2ffb37338760d741694486cf5418a38834c3ca1bd9c573098ee10d997
|
||||
checksum: 46a4054440361b25d13ecd75811bf239a6abb4830ce7f79b2b15ccd878758760
|
||||
- filename: .github/workflows/push-triggers.yml
|
||||
checksum: abc19ea38c8d7b79f15695d015709cc88a34a995181aaf12bc8344f940f3cbc4
|
||||
- filename: android/fastlane/Fastfile
|
||||
@@ -113,6 +115,16 @@ fileignoreconfig:
|
||||
checksum: a4e3772dc67a07ecbcfc58be0d6d4f7fa799cec7ac25bd269ac29459c8669ca4
|
||||
- filename: injitest/src/test/java/iosTestCases/CredentialRegistryTest.java
|
||||
checksum: b0808e0c511412cde21fd169a9bbeaf3b77cb48f25418e12d341cc3ce1df5898
|
||||
- filename: injitest/src/main/resources/Vids.json
|
||||
checksum: 8bcffed7a6dd565ae695e1b29de0655e10bd5c5420af2718defd593a687b8817
|
||||
- filename: injitest/src/main/java/inji/utils/UpdateNetworkSettings.java
|
||||
checksum: e249ce3e6b7f47abc183fe5a3637bb39ccb06900ef75b9b2f08426d1535e22aa
|
||||
- filename: injitest/src/test/java/androidTestCases/ShareVcTest.java
|
||||
checksum: a7e3e579b6ac05f95932638b61272142774d0690c13717c890e87374782ea509
|
||||
- filename: injitest/src/test/java/iosTestCases/ShareVcTest.java
|
||||
checksum: 1cf9b61d3fcea9b63b2b9f7dffe9b5a1848e196c39f77790b6c9d83f201c6197
|
||||
- filename: ios/RNPixelpassModule.swift
|
||||
checksum: 822a2421798d5c0669f4ab1b983194eb770cbef2aa30bf212d06bd959738c4ca
|
||||
- filename: components/BackupAndRestoreAllScreenBanner.tsx
|
||||
checksum: 2c98e7e83959c9dac4dd12da32f81483c3d334bd05e279637cf465475fbf54b8
|
||||
- filename: locales/en.json
|
||||
@@ -144,7 +156,7 @@ fileignoreconfig:
|
||||
- filename: shared/VCMetadata.ts
|
||||
checksum: e93f988415bf91064e2cf5fbc09ff6c7226798baa5da721fa0715d5d0d6afddf
|
||||
- filename: ios/Podfile.lock
|
||||
checksum: 0b4ed806e0fbecf60fb1135072d0a629666723fedcd960b6470bac0bb42a3e68
|
||||
checksum: b8c97d58a88207bae811db83074388cff249a83055a1f92ea7dee2f59b7a32c9
|
||||
- filename: components/BackupAndRestoreBannerNotification.tsx
|
||||
checksum: e465a9947727687d784d0cb9d8db1e28f765b0659bf4a3aa6d75643aa7b14102
|
||||
- filename: components/ActivityLogEvent.ts
|
||||
@@ -186,11 +198,11 @@ fileignoreconfig:
|
||||
- filename: screens/Home/IntroSlidersScreen.tsx
|
||||
checksum: 9880724461b194db7651737576ad2fd2db9cf3b4e732747f59be422a7ff4e4a1
|
||||
- filename: .env
|
||||
checksum: e4254ca79a1269161ac3e9d4870680a8650ac7dbdf61c39c084722a9e8925669
|
||||
checksum: ac76b852842c44ff5dac96c1fa5061e569bea4f54b3080d869a9dc25abd17991
|
||||
- filename: machines/VCItemMachine/VCItemMachine.typegen.ts
|
||||
checksum: 850b5d02636bef9e286fc0fbc4ffffbd38068f332c319302a906496f4bc1c8a1
|
||||
- filename: machines/VCItemMachine/VCItemEvents.ts
|
||||
checksum: 04e5758d4fa8bc37e8b66f7f51627a9e71ccbca7a046aa64e914f5cf855aa48b
|
||||
- filename: machines/VerifiableCredential/VCItemMachine/VCItemModel.ts
|
||||
checksum: 2a22331fe5f20d44c210b8970be0b934bfdf39bc999009305a9ba8f18e4d5469
|
||||
- filename: machines/VCItemMachine/VCItemGaurds.ts
|
||||
checksum: 4f32814fc26a0edaa54a42dbc9f9e1d899144eb059ac8da211d1738887871829
|
||||
- filename: machines/VCItemMachine/VCItemServices.ts
|
||||
@@ -317,8 +329,14 @@ fileignoreconfig:
|
||||
- filename: machines/VerifiableCredential/VCItemMachine/VCItemMachine.ts
|
||||
checksum: fdc0c23a7107eb713d20f60fda675f9e9fe8ef29c981d798d90e581dfee340c8
|
||||
checksum: 8ac74d2e5c6de179e460b86899eb048ad4c5bd67abc3d28c015e92335b8afe24
|
||||
- filename: machines/VerifiableCredential/VCItemMachine/VCItemServices.ts
|
||||
checksum: 1ce38602f148388940eec172a5c9be83de7a600adcae0ba9e8ac27e5ebc44641
|
||||
- filename: ios/RNPixelpassModule.m
|
||||
checksum: c91348eceec5edbffa03ba03f3f52a8e90ff7f942816c9609080d1647052fd66
|
||||
- filename: android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java
|
||||
checksum: 17f55840bab193bc353034445ba4fce53e1ce466e95f616c15a1351f8d2f23bc
|
||||
- filename: ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved
|
||||
checksum: b168940c6b487dc96fd22f564f2e187dae46f4fa5e4a64cf81c4d810b1c1ae78
|
||||
- filename: injitest/src/main/resources/Vids.json
|
||||
checksum: 8bcffed7a6dd565ae695e1b29de0655e10bd5c5420af2718defd593a687b8817
|
||||
- filename: injitest/src/main/java/inji/utils/UpdateNetworkSettings.java
|
||||
@@ -347,4 +365,8 @@ fileignoreconfig:
|
||||
checksum: b168940c6b487dc96fd22f564f2e187dae46f4fa5e4a64cf81c4d810b1c1ae78
|
||||
- filename: ios/Inji.xcodeproj/project.pbxproj
|
||||
checksum: 4359976ed4d1ac3206d76b87d3458d070027199c8569ba123436c4b5343aba74
|
||||
- filename: components/FaceScanner/FaceCompare.tsx
|
||||
checksum: 947b6d75543e2bf959ca2d95dd7224051e0b4ec2c28f7515f923701e22a932f0
|
||||
- filename: components/FaceScanner/LivenessDetection.tsx
|
||||
checksum: d4140a42ee9ca0f7c90e490f762d181a723fd9dd20db891cbbe53bfbd8f81632
|
||||
version: ""
|
||||
|
||||
@@ -145,12 +145,9 @@ jest.mock('react-native-gesture-handler', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@mosip/secure-keystore', () => ({
|
||||
sign: jest.fn(),
|
||||
encryptData: input => (input ? String(input) : 'mockedString'),
|
||||
decryptData: input => (input ? String(input) : 'mockedString'),
|
||||
deviceSupportsHardware: () => true,
|
||||
}));
|
||||
jest.mock('@invertase/react-native-apple-authentication', () => {});
|
||||
|
||||
jest.mock('react-native-share', () => {});
|
||||
|
||||
jest.mock('../machines/store', () => ({
|
||||
getItem: jest.fn(),
|
||||
|
||||
@@ -17,6 +17,12 @@ jest.mock('react-native', () => {
|
||||
SecureKeystore: {
|
||||
deviceSupportsHardware: jest.fn(),
|
||||
},
|
||||
RNSecureKeystoreModule: {
|
||||
sign: jest.fn(),
|
||||
encryptData: input => (input ? String(input) : 'mockedString'),
|
||||
decryptData: input => (input ? String(input) : 'mockedString'),
|
||||
deviceSupportsHardware: () => true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('getActionText', () => {
|
||||
mockIl18nfn = jest.fn();
|
||||
activityLog = new ActivityLog({
|
||||
id: 'mockId',
|
||||
idType: 'mockIDtype',
|
||||
idType: ['mockIDtype'] as string[],
|
||||
_vcKey: 'mock_vc_key',
|
||||
type: 'mockType',
|
||||
timestamp: 1234,
|
||||
@@ -38,18 +38,17 @@ describe('getActionText', () => {
|
||||
return 'National ID';
|
||||
}
|
||||
});
|
||||
getActionText(activityLog, mockIl18nfn);
|
||||
expect(mockIl18nfn).toHaveBeenCalledWith(`VcDetails:mockIDtype`);
|
||||
getActionText(activityLog, mockIl18nfn, {});
|
||||
expect(mockIl18nfn).toHaveBeenCalledWith('mockType', {
|
||||
idType: 'National ID',
|
||||
idType: 'nationalCard',
|
||||
id: 'mockId',
|
||||
});
|
||||
expect(mockIl18nfn).toHaveBeenCalledTimes(2);
|
||||
expect(mockIl18nfn).toHaveBeenCalledTimes(1);
|
||||
// TODO: assert the returned string
|
||||
});
|
||||
it('should not fetch id type from translation file mock', () => {
|
||||
activityLog.idType = undefined;
|
||||
getActionText(activityLog, mockIl18nfn);
|
||||
getActionText(activityLog, mockIl18nfn, {});
|
||||
expect(mockIl18nfn).toHaveBeenCalledWith('mockType', {
|
||||
idType: '',
|
||||
id: 'mockId',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {getIdType} from './VC/common/VCUtils';
|
||||
|
||||
export type ActivityLogType =
|
||||
| '' // replacement for undefined
|
||||
| 'VC_SHARED'
|
||||
@@ -18,21 +20,23 @@ export type ActivityLogType =
|
||||
|
||||
export class ActivityLog {
|
||||
id: string;
|
||||
idType: string;
|
||||
idType: string[];
|
||||
_vcKey: string;
|
||||
timestamp: number;
|
||||
deviceName: string;
|
||||
vcLabel: string;
|
||||
type: ActivityLogType;
|
||||
issuer: string;
|
||||
|
||||
constructor({
|
||||
id = '',
|
||||
idType = '',
|
||||
idType = [],
|
||||
_vcKey = '',
|
||||
type = '',
|
||||
timestamp = Date.now(),
|
||||
deviceName = '',
|
||||
vcLabel = '',
|
||||
issuer = '',
|
||||
} = {}) {
|
||||
this.id = id;
|
||||
this.idType = idType;
|
||||
@@ -41,6 +45,7 @@ export class ActivityLog {
|
||||
this.timestamp = timestamp;
|
||||
this.deviceName = deviceName;
|
||||
this.vcLabel = vcLabel;
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
static logTamperedVCs() {
|
||||
@@ -50,13 +55,14 @@ export class ActivityLog {
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: '',
|
||||
issuer: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function getActionText(activity: ActivityLog, t) {
|
||||
if (activity.idType && activity.idType !== '') {
|
||||
let cardType = t(`VcDetails:${activity.idType}`);
|
||||
export function getActionText(activity: ActivityLog, t, wellknown: Object) {
|
||||
if (activity.idType && activity.idType.length !== 0) {
|
||||
const cardType = getIdType(wellknown, activity.idType);
|
||||
return `${t(activity.type, {idType: cardType, id: activity.id})}`;
|
||||
}
|
||||
return `${t(activity.type, {idType: '', id: activity.id})}`;
|
||||
|
||||
@@ -5,15 +5,21 @@ import {useTranslation} from 'react-i18next';
|
||||
import * as DateFnsLocale from 'date-fns/locale';
|
||||
import {TextItem} from './ui/TextItem';
|
||||
import {ActivityLog, getActionText} from './ActivityLogEvent';
|
||||
import {useHistoryTab} from '../screens/History/HistoryScreenController';
|
||||
|
||||
export const ActivityLogText: React.FC<{activity: ActivityLog}> = props => {
|
||||
const {t, i18n} = useTranslation('ActivityLogText');
|
||||
const historyController = useHistoryTab();
|
||||
const {activity} = props;
|
||||
|
||||
return (
|
||||
<TextItem
|
||||
label={getActionLabel(activity, i18n.language)}
|
||||
text={getActionText(activity, t)}
|
||||
text={getActionText(
|
||||
activity,
|
||||
t,
|
||||
historyController.getWellKnownIssuerMap(activity.issuer),
|
||||
)}
|
||||
divider
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -78,9 +78,7 @@ export const BannerNotificationContainer: React.FC<
|
||||
<BannerNotification
|
||||
type={verificationStatus.statusType}
|
||||
message={t(`VcVerificationBanner:${verificationStatus?.statusType}`, {
|
||||
vcDetails: `${t(`VcDetails:${verificationStatus.vcType}`)} ${
|
||||
verificationStatus.vcNumber
|
||||
}`,
|
||||
vcDetails: `${verificationStatus.vcType} ${verificationStatus.vcNumber}`,
|
||||
})}
|
||||
onClosePress={bannerNotificationController.RESET_VERIFICATION_STATUS}
|
||||
key={'reVerificationInProgress'}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Camera, CameraType } from 'expo-camera';
|
||||
import { View, TouchableOpacity } from 'react-native';
|
||||
import {Camera, CameraType} from 'expo-camera';
|
||||
import {View, TouchableOpacity} from 'react-native';
|
||||
import {SvgImage} from '../ui/svg';
|
||||
import { Text, Column, Row, Centered } from '../ui';
|
||||
import {Text, Column, Row, Centered} from '../ui';
|
||||
import {RotatingIcon} from '../RotatingIcon';
|
||||
import { Theme } from '../ui/styleUtils';
|
||||
import {Theme} from '../ui/styleUtils';
|
||||
import testIDProps from '../../shared/commonUtil';
|
||||
|
||||
const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
@@ -13,11 +13,11 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
isCapturing,
|
||||
isVerifying,
|
||||
service,
|
||||
t
|
||||
t,
|
||||
}) => {
|
||||
return (
|
||||
<Column fill align="space-between" style={{ backgroundColor: '#ffffff' }}>
|
||||
<View style={{ flex: 2, marginTop: 15 }}>
|
||||
<Column fill align="space-between" style={{backgroundColor: '#ffffff'}}>
|
||||
<View style={{flex: 2, marginTop: 15}}>
|
||||
<View style={Theme.CameraEnabledStyles.scannerContainer}>
|
||||
<View>
|
||||
<Camera
|
||||
@@ -33,8 +33,7 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
align="center"
|
||||
weight="semibold"
|
||||
style={Theme.TextStyles.base}
|
||||
margin="80 57"
|
||||
>
|
||||
margin="80 57">
|
||||
{t('imageCaptureGuide')}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -47,7 +46,9 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
<TouchableOpacity onPress={() => service.send('CAPTURE')}>
|
||||
{SvgImage.CameraCaptureIcon()}
|
||||
</TouchableOpacity>
|
||||
<Text testID="captureText" style={Theme.CameraEnabledStyles.iconText}>
|
||||
<Text
|
||||
testID="captureText"
|
||||
style={Theme.CameraEnabledStyles.iconText}>
|
||||
{t('capture')}
|
||||
</Text>
|
||||
</Centered>
|
||||
@@ -55,7 +56,9 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
<TouchableOpacity onPress={() => service.send('FLIP_CAMERA')}>
|
||||
{SvgImage.FlipCameraIcon()}
|
||||
</TouchableOpacity>
|
||||
<Text testID="flipCameraText" style={Theme.CameraEnabledStyles.iconText}>
|
||||
<Text
|
||||
testID="flipCameraText"
|
||||
style={Theme.CameraEnabledStyles.iconText}>
|
||||
{t('flipCamera')}
|
||||
</Text>
|
||||
</Centered>
|
||||
@@ -69,10 +72,10 @@ const FaceCompare: React.FC<FaceCompareProps> = ({
|
||||
export default FaceCompare;
|
||||
|
||||
interface FaceCompareProps {
|
||||
whichCamera: CameraType;
|
||||
setCameraRef:(node: Camera) => void;
|
||||
isCapturing: boolean;
|
||||
isVerifying: boolean;
|
||||
service: any;
|
||||
t: (key: string) => string;
|
||||
}
|
||||
whichCamera: CameraType;
|
||||
setCameraRef: (node: Camera) => void;
|
||||
isCapturing: boolean;
|
||||
isVerifying: boolean;
|
||||
service: any;
|
||||
t: (key: string) => string;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ export const imageCaptureConfig = {
|
||||
imageType: ImageType.jpg,
|
||||
};
|
||||
|
||||
export const faceDetectorConfig : FaceDetectorConfig= {
|
||||
export const faceDetectorConfig: FaceDetectorConfig = {
|
||||
mode: FaceDetector.FaceDetectorMode.accurate,
|
||||
detectLandmarks: FaceDetector.FaceDetectorLandmarks.all,
|
||||
runClassifications: FaceDetector.FaceDetectorClassifications.all,
|
||||
@@ -258,7 +258,7 @@ export interface FaceDetectorConfig {
|
||||
mode: FaceDetector.FaceDetectorMode;
|
||||
detectLandmarks: FaceDetector.FaceDetectorLandmarks;
|
||||
runClassifications: FaceDetector.FaceDetectorClassifications;
|
||||
contourMode: FaceDetector.FaceDetectorClassifications;
|
||||
contourMode: FaceDetector.FaceDetectorClassifications;
|
||||
minDetectionInterval: number;
|
||||
tracking: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Camera, CameraType } from 'expo-camera';
|
||||
import { View, TouchableOpacity } from 'react-native';
|
||||
import {Camera, CameraType} from 'expo-camera';
|
||||
import {View, TouchableOpacity} from 'react-native';
|
||||
import Spinner from 'react-native-spinkit';
|
||||
import { Column, Text } from '.././ui';
|
||||
import { Theme } from '.././ui/styleUtils';
|
||||
import Svg, { Defs, Mask, Rect, Ellipse } from 'react-native-svg';
|
||||
import {Column, Text} from '.././ui';
|
||||
import {Theme} from '.././ui/styleUtils';
|
||||
import Svg, {Defs, Mask, Rect, Ellipse} from 'react-native-svg';
|
||||
import testIDProps from '../../shared/commonUtil';
|
||||
import { FaceDetectorConfig } from './FaceScannerHelper';
|
||||
import {FaceDetectorConfig} from './FaceScannerHelper';
|
||||
|
||||
const LivenessDetection: React.FC<LivenessDetectionProps> = ({
|
||||
screenColor,
|
||||
@@ -18,19 +18,24 @@ const LivenessDetection: React.FC<LivenessDetectionProps> = ({
|
||||
handleOnCancel,
|
||||
opacity,
|
||||
setOpacity,
|
||||
t
|
||||
t,
|
||||
}) => {
|
||||
return (
|
||||
<Column fill align='space-between' style={{ backgroundColor: screenColor }}>
|
||||
<Column fill align="space-between" style={{backgroundColor: screenColor}}>
|
||||
<View style={Theme.CameraEnabledStyles.guideContainer}>
|
||||
<View style={Theme.CameraEnabledStyles.guideContentContainer}>
|
||||
<Spinner type="ThreeBounce" color={Theme.Colors.Loading} />
|
||||
<Text testID="captureInfoText" size="small" weight="bold" color="black" align="center">
|
||||
<Text
|
||||
testID="captureInfoText"
|
||||
size="small"
|
||||
weight="bold"
|
||||
color="black"
|
||||
align="center">
|
||||
{infoText}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{ flex: 2, marginTop: 15 }}>
|
||||
<View style={{flex: 2, marginTop: 15}}>
|
||||
<View style={Theme.CameraEnabledStyles.scannerContainer}>
|
||||
<View>
|
||||
<Camera
|
||||
@@ -41,14 +46,19 @@ const LivenessDetection: React.FC<LivenessDetectionProps> = ({
|
||||
onFacesDetected={handleFacesDetected}
|
||||
faceDetectorSettings={faceDetectorConfig}
|
||||
/>
|
||||
<Svg height="100%" width="100%" style={{ position: 'absolute' }}>
|
||||
<Svg height="100%" width="100%" style={{position: 'absolute'}}>
|
||||
<Defs>
|
||||
<Mask id="mask" x="0" y="0" height="100%" width="100%">
|
||||
<Rect height="100%" width="100%" fill="#fff" opacity="0.3" />
|
||||
<Ellipse rx="38%" ry="45%" cx="50%" cy="50%" fill="black" />
|
||||
</Mask>
|
||||
</Defs>
|
||||
<Rect height="100%" width="100%" fill="rgba(0, 0, 0, 0.8)" mask="url(#mask)" />
|
||||
<Rect
|
||||
height="100%"
|
||||
width="100%"
|
||||
fill="rgba(0, 0, 0, 0.8)"
|
||||
mask="url(#mask)"
|
||||
/>
|
||||
</Svg>
|
||||
</View>
|
||||
</View>
|
||||
@@ -56,12 +66,16 @@ const LivenessDetection: React.FC<LivenessDetectionProps> = ({
|
||||
<View style={Theme.CameraEnabledStyles.buttonContainer}>
|
||||
<TouchableOpacity
|
||||
{...testIDProps('cancel')}
|
||||
style={[Theme.CameraEnabledStyles.cancelButton, { opacity }]}
|
||||
style={[Theme.CameraEnabledStyles.cancelButton, {opacity}]}
|
||||
onPressIn={() => setOpacity(0.5)}
|
||||
onPressOut={() => setOpacity(1)}
|
||||
onPress={handleOnCancel}
|
||||
>
|
||||
<Text testID="cancelText" size="small" weight="bold" margin="8" color="black">
|
||||
onPress={handleOnCancel}>
|
||||
<Text
|
||||
testID="cancelText"
|
||||
size="small"
|
||||
weight="bold"
|
||||
margin="8"
|
||||
color="black">
|
||||
{t('cancel')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
@@ -73,14 +87,14 @@ const LivenessDetection: React.FC<LivenessDetectionProps> = ({
|
||||
export default LivenessDetection;
|
||||
|
||||
interface LivenessDetectionProps {
|
||||
screenColor: string;
|
||||
infoText: string;
|
||||
whichCamera: CameraType;
|
||||
setCameraRef: (node: Camera) => void;
|
||||
handleFacesDetected: (faces: any) => Promise<void>;
|
||||
faceDetectorConfig: FaceDetectorConfig;
|
||||
handleOnCancel: () => void;
|
||||
opacity: number;
|
||||
setOpacity: (opacity: number) => void;
|
||||
t: (key: string) => string;
|
||||
}
|
||||
screenColor: string;
|
||||
infoText: string;
|
||||
whichCamera: CameraType;
|
||||
setCameraRef: (node: Camera) => void;
|
||||
handleFacesDetected: (faces: any) => Promise<void>;
|
||||
faceDetectorConfig: FaceDetectorConfig;
|
||||
handleOnCancel: () => void;
|
||||
opacity: number;
|
||||
setOpacity: (opacity: number) => void;
|
||||
t: (key: string) => string;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import {ImageBackground, Pressable, Image, View} from 'react-native';
|
||||
import {getLocalizedField} from '../../../i18n';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {KebabPopUp} from '../../KebabPopUp';
|
||||
import {VerifiableCredential} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import {Credential} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import {Column, Row} from '../../ui';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
import {CheckBox, Icon} from 'react-native-elements';
|
||||
@@ -13,7 +13,7 @@ import {isVCLoaded, getBackgroundColour} from '../common/VCUtils';
|
||||
import {VCItemFieldValue} from '../common/VCItemField';
|
||||
import {WalletBinding} from '../../../screens/Home/MyVcs/WalletBinding';
|
||||
import {VCVerification} from '../../VCVerification';
|
||||
import {Issuers} from '../../../shared/openId4VCI/Utils';
|
||||
import {isActivationNeeded} from '../../../shared/openId4VCI/Utils';
|
||||
import {VCItemContainerFlowType} from '../../../shared/Utils';
|
||||
import {RemoveVcWarningOverlay} from '../../../screens/Home/MyVcs/RemoveVcWarningOverlay';
|
||||
import {HistoryTab} from '../../../screens/Home/MyVcs/HistoryTab';
|
||||
@@ -87,10 +87,10 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
|
||||
|
||||
{!Object.values(VCItemContainerFlowType).includes(props.flow) && (
|
||||
<>
|
||||
{props.vcMetadata.issuer === Issuers.Sunbird ||
|
||||
props.walletBindingResponse
|
||||
? SvgImage.walletActivatedIcon()
|
||||
: SvgImage.walletUnActivatedIcon()}
|
||||
{!props.walletBindingResponse &&
|
||||
isActivationNeeded(props.verifiableCredentialData?.issuer)
|
||||
? SvgImage.walletUnActivatedIcon()
|
||||
: SvgImage.walletActivatedIcon()}
|
||||
<Pressable
|
||||
onPress={props.KEBAB_POPUP}
|
||||
accessible={false}
|
||||
@@ -130,7 +130,7 @@ export const VCCardViewContent: React.FC<VCItemContentProps> = props => {
|
||||
|
||||
export interface VCItemContentProps {
|
||||
context: any;
|
||||
credential: VerifiableCredential;
|
||||
credential: Credential;
|
||||
verifiableCredentialData: any;
|
||||
fields: [];
|
||||
wellknown: {};
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {Image, ImageBackground, View} from 'react-native';
|
||||
import {
|
||||
Credential,
|
||||
VerifiableCredential,
|
||||
WalletBindingResponse,
|
||||
} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import {
|
||||
Credential,
|
||||
CredentialSubject,
|
||||
CredentialTypes,
|
||||
IssuerWellknownResponse,
|
||||
VerifiableCredential,
|
||||
} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import i18n, {getLocalizedField} from '../../../i18n';
|
||||
@@ -8,10 +11,10 @@ import {VCItemField} from './VCItemField';
|
||||
import React from 'react';
|
||||
import {Theme} from '../../ui/styleUtils';
|
||||
import {CREDENTIAL_REGISTRY_EDIT} from 'react-native-dotenv';
|
||||
import {getIDType} from '../../../shared/openId4VCI/Utils';
|
||||
import {VCVerification} from '../../VCVerification';
|
||||
import {MIMOTO_BASE_URL} from '../../../shared/constants';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {VCItemDetailsProps} from '../Views/VCDetailView';
|
||||
import {getSelectedCredentialTypeDetails} from '../../../shared/openId4VCI/Utils';
|
||||
|
||||
export const CARD_VIEW_DEFAULT_FIELDS = ['fullName'];
|
||||
export const DETAIL_VIEW_DEFAULT_FIELDS = [
|
||||
@@ -26,8 +29,6 @@ export const DETAIL_VIEW_DEFAULT_FIELDS = [
|
||||
//todo UIN & VID to be removed once we get the fields in the wellknown endpoint
|
||||
export const CARD_VIEW_ADD_ON_FIELDS = ['UIN', 'VID'];
|
||||
export const DETAIL_VIEW_ADD_ON_FIELDS = [
|
||||
'UIN',
|
||||
'VID',
|
||||
'status',
|
||||
'credentialRegistry',
|
||||
'idType',
|
||||
@@ -46,18 +47,11 @@ export const BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS = [
|
||||
];
|
||||
|
||||
export const getFieldValue = (
|
||||
verifiableCredential: VerifiableCredential,
|
||||
verifiableCredential: Credential,
|
||||
field: string,
|
||||
wellknown: any,
|
||||
props: any,
|
||||
) => {
|
||||
const {t} = useTranslation();
|
||||
const date = new Date(
|
||||
getLocalizedField(verifiableCredential?.credentialSubject[field]),
|
||||
).toString();
|
||||
if (date !== 'Invalid Date') {
|
||||
return formattedDateTime(date);
|
||||
}
|
||||
switch (field) {
|
||||
case 'status':
|
||||
return (
|
||||
@@ -67,7 +61,7 @@ export const getFieldValue = (
|
||||
/>
|
||||
);
|
||||
case 'idType':
|
||||
return t(`VcDetails:${getIDType(verifiableCredential)}`);
|
||||
return getIdType(wellknown);
|
||||
case 'credentialRegistry':
|
||||
return props?.vc?.credentialRegistry;
|
||||
case 'address':
|
||||
@@ -77,51 +71,22 @@ export const getFieldValue = (
|
||||
default: {
|
||||
const fieldValue = verifiableCredential?.credentialSubject[field];
|
||||
if (Array.isArray(fieldValue) && typeof fieldValue[0] !== 'object') {
|
||||
return fieldValue;
|
||||
return fieldValue.join(', ');
|
||||
}
|
||||
return getLocalizedField(fieldValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getCredentialDefinition = (
|
||||
wellknown: any,
|
||||
vcCredentialTypes: Object[],
|
||||
) => {
|
||||
if (Array.isArray(wellknown.credentials_supported)) {
|
||||
return wellknown.credentials_supported[0].credential_definition;
|
||||
} else {
|
||||
for (const supportedCredential in wellknown.credentials_supported) {
|
||||
const credentialDefinition =
|
||||
wellknown.credentials_supported[supportedCredential]
|
||||
.credential_definition;
|
||||
if (
|
||||
JSON.stringify(credentialDefinition.type) ===
|
||||
JSON.stringify(vcCredentialTypes)
|
||||
) {
|
||||
return credentialDefinition;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const getFieldName = (
|
||||
field: string,
|
||||
wellknown: any,
|
||||
vcCredentialTypes: Object[],
|
||||
) => {
|
||||
if (wellknown && wellknown.credentials_supported) {
|
||||
const credentialDefinition = getCredentialDefinition(
|
||||
wellknown,
|
||||
vcCredentialTypes,
|
||||
);
|
||||
export const getFieldName = (field: string, wellknown: any) => {
|
||||
if (wellknown) {
|
||||
const credentialDefinition = wellknown.credential_definition;
|
||||
if (!credentialDefinition) {
|
||||
console.error(
|
||||
'Credential definition is not available for the selected credential type',
|
||||
);
|
||||
}
|
||||
let fieldObj = credentialDefinition.credentialSubject[field];
|
||||
let fieldObj = credentialDefinition?.credentialSubject[field];
|
||||
if (fieldObj) {
|
||||
const newFieldObj = fieldObj.display.map(obj => {
|
||||
return {language: obj.locale, value: obj.name};
|
||||
@@ -133,20 +98,11 @@ export const getFieldName = (
|
||||
};
|
||||
|
||||
export const getBackgroundColour = (wellknown: any) => {
|
||||
if (wellknown && wellknown.credentials_supported[0]?.display) {
|
||||
return {
|
||||
backgroundColor: wellknown.credentials_supported[0].display[0]
|
||||
?.background_color
|
||||
? wellknown.credentials_supported[0].display[0].background_color
|
||||
: Theme.Colors.textValue,
|
||||
};
|
||||
}
|
||||
return wellknown?.display[0]?.background_color ?? Theme.Colors.textValue;
|
||||
};
|
||||
|
||||
export const getTextColor = (wellknown: any, defaultColor: string) => {
|
||||
return (
|
||||
wellknown?.credentials_supported[0]?.display[0]?.text_color ?? defaultColor
|
||||
);
|
||||
return wellknown?.display[0]?.text_color ?? defaultColor;
|
||||
};
|
||||
|
||||
export function getAddressFields() {
|
||||
@@ -174,26 +130,14 @@ function getFullAddress(credential: CredentialSubject) {
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
function formattedDateTime(timeStamp: any) {
|
||||
if (timeStamp) {
|
||||
const options = {year: 'numeric', month: '2-digit', day: '2-digit'};
|
||||
return new Date(timeStamp).toLocaleDateString('en-US', options);
|
||||
}
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
export const fieldItemIterator = (
|
||||
fields: any[],
|
||||
verifiableCredential: any,
|
||||
verifiableCredential: VerifiableCredential | Credential,
|
||||
wellknown: any,
|
||||
props: any,
|
||||
props: VCItemDetailsProps,
|
||||
) => {
|
||||
return fields.map(field => {
|
||||
const fieldName = getFieldName(
|
||||
field,
|
||||
wellknown,
|
||||
props.verifiableCredentialData.vcCredentialTypes,
|
||||
);
|
||||
const fieldName = getFieldName(field, wellknown);
|
||||
const fieldValue = getFieldValue(
|
||||
verifiableCredential,
|
||||
field,
|
||||
@@ -225,7 +169,10 @@ export const fieldItemIterator = (
|
||||
});
|
||||
};
|
||||
|
||||
export const isVCLoaded = (verifiableCredential: any, fields: string[]) => {
|
||||
export const isVCLoaded = (
|
||||
verifiableCredential: Credential,
|
||||
fields: string[],
|
||||
) => {
|
||||
return verifiableCredential != null && fields.length > 0;
|
||||
};
|
||||
|
||||
@@ -235,3 +182,50 @@ export const getMosipLogo = () => {
|
||||
alt_text: 'a square logo of mosip',
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param wellknown (either supportedCredential's wellknown or whole well known response of issuer)
|
||||
* @param idType
|
||||
* @returns id Type translations (Eg - National ID)
|
||||
*
|
||||
* supportedCredential's wellknown is passed from getActivityText after fresh download
|
||||
* & all other consumers pass whole well known response of issuer
|
||||
*/
|
||||
export const getIdType = (
|
||||
wellknown: CredentialTypes | IssuerWellknownResponse,
|
||||
idType?: string[],
|
||||
) => {
|
||||
if (wellknown && wellknown?.display) {
|
||||
const idTypeObj = wellknown.display.map((displayProps: any) => {
|
||||
return {language: displayProps.locale, value: displayProps.name};
|
||||
});
|
||||
return getLocalizedField(idTypeObj);
|
||||
} else if (
|
||||
wellknown &&
|
||||
Object.keys(wellknown).length > 0 &&
|
||||
idType !== undefined
|
||||
) {
|
||||
let supportedCredentialsWellknown;
|
||||
wellknown = JSON.parse(wellknown) as Object[];
|
||||
if (!!!wellknown['credentials_supported']) {
|
||||
return i18n.t('VcDetails:nationalCard');
|
||||
}
|
||||
supportedCredentialsWellknown = getSelectedCredentialTypeDetails(
|
||||
wellknown,
|
||||
idType,
|
||||
);
|
||||
if (Object.keys(supportedCredentialsWellknown).length === 0) {
|
||||
return i18n.t('VcDetails:nationalCard');
|
||||
}
|
||||
return getIdType(supportedCredentialsWellknown);
|
||||
} else {
|
||||
return i18n.t('VcDetails:nationalCard');
|
||||
}
|
||||
};
|
||||
|
||||
export const getCredentialTypes = (
|
||||
credential: Credential | VerifiableCredential,
|
||||
): string[] => {
|
||||
return (credential?.credentialTypes as string[]) ?? ['VerifiableCredential'];
|
||||
};
|
||||
|
||||
@@ -19,64 +19,65 @@ export const Modal: React.FC<ModalProps> = props => {
|
||||
visible={props.isVisible}
|
||||
onShow={props.onShow}
|
||||
onRequestClose={props.onDismiss}>
|
||||
<Column {...(props.showHeader ? { fill: true, safe: true } : { fill: true })}>
|
||||
{ props.showHeader ? (
|
||||
<Row elevation={props.headerElevation}>
|
||||
<View style={props.modalStyle}>
|
||||
{props.headerRight && !props.arrowLeft ? (
|
||||
<Icon
|
||||
{...testIDProps('closeModal')}
|
||||
name={I18nManager.isRTL ? 'chevron-right' : 'chevron-left'}
|
||||
onPress={props.onDismiss}
|
||||
color={Theme.Colors.Icon}
|
||||
/>
|
||||
) : null}
|
||||
{props.arrowLeft && props.onDismiss ? (
|
||||
<BackButton onPress={props.onDismiss} />
|
||||
) : null}
|
||||
<Row
|
||||
fill
|
||||
align={props.headerLeft ? 'flex-start' : 'center'}
|
||||
margin={props.arrowLeft ? '16 0 0 -15' : '16 0 0 10'}>
|
||||
<Column>
|
||||
<Text testID={props.testID} style={Theme.TextStyles.header}>
|
||||
{props.headerTitle || props.headerLeft}
|
||||
</Text>
|
||||
{!props.requester ? (
|
||||
<Text
|
||||
weight="semibold"
|
||||
style={Theme.TextStyles.small}
|
||||
color={
|
||||
props.headerLabelColor
|
||||
? props.headerLabelColor
|
||||
: Theme.Colors.textLabel
|
||||
}>
|
||||
{props.headerLabel}
|
||||
</Text>
|
||||
) : (
|
||||
<Text
|
||||
weight="semibold"
|
||||
style={Theme.TextStyles.small}
|
||||
color={Theme.Colors.IconBg}>
|
||||
<DeviceInfoList deviceInfo={controller.receiverInfo} />
|
||||
</Text>
|
||||
)}
|
||||
</Column>
|
||||
</Row>
|
||||
{props.headerRight != null ||
|
||||
props.arrowLeft ||
|
||||
(props.showClose && (
|
||||
<Column {...(props.showHeader ? {fill: true, safe: true} : {fill: true})}>
|
||||
{props.showHeader ? (
|
||||
<Row elevation={props.headerElevation}>
|
||||
<View style={props.modalStyle}>
|
||||
{props.headerRight && !props.arrowLeft ? (
|
||||
<Icon
|
||||
{...testIDProps('close')}
|
||||
name="close"
|
||||
{...testIDProps('closeModal')}
|
||||
name={I18nManager.isRTL ? 'chevron-right' : 'chevron-left'}
|
||||
onPress={props.onDismiss}
|
||||
color={Theme.Colors.Details}
|
||||
size={27}
|
||||
color={Theme.Colors.Icon}
|
||||
/>
|
||||
))}
|
||||
{props.headerRight && props.headerRight}
|
||||
</View>
|
||||
</Row> ) : null}
|
||||
) : null}
|
||||
{props.arrowLeft && props.onDismiss ? (
|
||||
<BackButton onPress={props.onDismiss} />
|
||||
) : null}
|
||||
<Row
|
||||
fill
|
||||
align={props.headerLeft ? 'flex-start' : 'center'}
|
||||
margin={props.arrowLeft ? '16 0 0 -15' : '16 0 0 10'}>
|
||||
<Column>
|
||||
<Text testID={props.testID} style={Theme.TextStyles.header}>
|
||||
{props.headerTitle || props.headerLeft}
|
||||
</Text>
|
||||
{!props.requester ? (
|
||||
<Text
|
||||
weight="semibold"
|
||||
style={Theme.TextStyles.small}
|
||||
color={
|
||||
props.headerLabelColor
|
||||
? props.headerLabelColor
|
||||
: Theme.Colors.textLabel
|
||||
}>
|
||||
{props.headerLabel}
|
||||
</Text>
|
||||
) : (
|
||||
<Text
|
||||
weight="semibold"
|
||||
style={Theme.TextStyles.small}
|
||||
color={Theme.Colors.IconBg}>
|
||||
<DeviceInfoList deviceInfo={controller.receiverInfo} />
|
||||
</Text>
|
||||
)}
|
||||
</Column>
|
||||
</Row>
|
||||
{props.headerRight != null ||
|
||||
props.arrowLeft ||
|
||||
(props.showClose && (
|
||||
<Icon
|
||||
{...testIDProps('close')}
|
||||
name="close"
|
||||
onPress={props.onDismiss}
|
||||
color={Theme.Colors.Details}
|
||||
size={27}
|
||||
/>
|
||||
))}
|
||||
{props.headerRight && props.headerRight}
|
||||
</View>
|
||||
</Row>
|
||||
) : null}
|
||||
{props.children}
|
||||
</Column>
|
||||
</RNModal>
|
||||
|
||||
@@ -21,7 +21,7 @@ import ReceiveCard from '../../assets/Receive_Card.svg';
|
||||
import ReceivedCards from '../../assets/Received_Cards.svg';
|
||||
import ProgressIcon from '../../assets/Progress_Icon1.svg';
|
||||
import testIDProps from '../../shared/commonUtil';
|
||||
import Logo from '../../assets/Inji_Logo';
|
||||
import Logo from '../../assets/Inji_Logo.svg';
|
||||
import WarningLogo from '../../assets/Warning_Icon.svg';
|
||||
import OtpVerificationIcon from '../../assets/Otp_Verification_Icon.svg';
|
||||
import FlipCameraIcon from '../../assets/Flip_Camera_Icon.svg';
|
||||
|
||||
@@ -1549,8 +1549,8 @@ export const DefaultTheme = {
|
||||
},
|
||||
scannerContainer: {
|
||||
borderRadius: 24,
|
||||
height: 320,
|
||||
width: 300,
|
||||
height: 350,
|
||||
width: 320,
|
||||
marginTop: 40,
|
||||
backgroundColor: Colors.White,
|
||||
borderWidth: 1,
|
||||
@@ -1559,12 +1559,11 @@ export const DefaultTheme = {
|
||||
}),
|
||||
|
||||
CameraEnabledStyles: StyleSheet.create({
|
||||
container: {marginTop: 20, marginBottom: 20},
|
||||
scannerContainer: {
|
||||
borderRadius: 24,
|
||||
alignSelf: 'center',
|
||||
height: 320,
|
||||
width: 300,
|
||||
height: 350,
|
||||
width: 320,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
scanner: {
|
||||
|
||||
@@ -1549,8 +1549,8 @@ export const PurpleTheme = {
|
||||
},
|
||||
scannerContainer: {
|
||||
borderRadius: 24,
|
||||
height: 320,
|
||||
width: 300,
|
||||
height: 350,
|
||||
width: 320,
|
||||
marginTop: 40,
|
||||
backgroundColor: Colors.White,
|
||||
borderWidth: 1,
|
||||
@@ -1558,12 +1558,11 @@ export const PurpleTheme = {
|
||||
},
|
||||
}),
|
||||
CameraEnabledStyles: StyleSheet.create({
|
||||
container: {marginTop: 20, marginBottom: 20},
|
||||
scannerContainer: {
|
||||
borderRadius: 24,
|
||||
alignSelf: 'center',
|
||||
height: 320,
|
||||
width: 300,
|
||||
height: 350,
|
||||
width: 320,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
scanner: {
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
ErrorMessage,
|
||||
getIdType,
|
||||
Issuers_Key_Ref,
|
||||
updateVCmetadataOfCredentialWrapper,
|
||||
} from '../../shared/openId4VCI/Utils';
|
||||
import {ErrorMessage, Issuers_Key_Ref} from '../../shared/openId4VCI/Utils';
|
||||
import {
|
||||
MY_VCS_STORE_KEY,
|
||||
NETWORK_REQUEST_FAILED,
|
||||
@@ -61,12 +56,12 @@ export const IssuersActions = (model: any) => {
|
||||
setSelectedCredentialType: model.assign({
|
||||
selectedCredentialType: (_: any, event: any) => event.credType,
|
||||
}),
|
||||
setSupportedCredentialTypes: model.assign({
|
||||
supportedCredentialTypes: (_: any, event: any) => event.data,
|
||||
}),
|
||||
resetSelectedCredentialType: model.assign({
|
||||
selectedCredentialType: {},
|
||||
}),
|
||||
setCredentialTypes: model.assign({
|
||||
credentialTypes: (_: any, event: any) => event.data.supportedCredentials,
|
||||
}),
|
||||
setError: model.assign({
|
||||
errorMessage: (_: any, event: any) => {
|
||||
console.error('Error occurred ', event.data.message);
|
||||
@@ -119,10 +114,10 @@ export const IssuersActions = (model: any) => {
|
||||
),
|
||||
|
||||
setMetadataInCredentialData: (context: any) => {
|
||||
return updateVCmetadataOfCredentialWrapper(
|
||||
context,
|
||||
context.credentialWrapper,
|
||||
);
|
||||
context.credentialWrapper = {
|
||||
...context.credentialWrapper,
|
||||
vcMetadata: context.vcMetadata,
|
||||
};
|
||||
},
|
||||
|
||||
setVCMetadata: assign({
|
||||
@@ -132,11 +127,13 @@ export const IssuersActions = (model: any) => {
|
||||
}),
|
||||
|
||||
storeVerifiableCredentialData: send(
|
||||
(context: any) =>
|
||||
StoreEvents.SET(getVCMetadata(context).getVcKey(), {
|
||||
(context: any) => {
|
||||
const vcMeatadata = getVCMetadata(context);
|
||||
return StoreEvents.SET(vcMeatadata.getVcKey(), {
|
||||
...context.credentialWrapper,
|
||||
vcMetadata: getVCMetadata(context),
|
||||
}),
|
||||
vcMetadata: vcMeatadata,
|
||||
});
|
||||
},
|
||||
{
|
||||
to: (context: any) => context.serviceRefs.store,
|
||||
},
|
||||
@@ -201,15 +198,21 @@ export const IssuersActions = (model: any) => {
|
||||
|
||||
logDownloaded: send(
|
||||
context => {
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: getVCMetadata(context).getVcKey(),
|
||||
type: 'VC_DOWNLOADED',
|
||||
id: getVCMetadata(context).id,
|
||||
idType: getIdType(getVCMetadata(context).issuer),
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: getVCMetadata(context).id,
|
||||
});
|
||||
const vcMetadata = getVCMetadata(context);
|
||||
return ActivityLogEvents.LOG_ACTIVITY(
|
||||
{
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: 'VC_DOWNLOADED',
|
||||
id: vcMetadata.id,
|
||||
idType:
|
||||
context.credentialWrapper.verifiableCredential.credentialTypes,
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: vcMetadata.id,
|
||||
issuer: context.selectedIssuerId,
|
||||
},
|
||||
context.selectedCredentialType,
|
||||
);
|
||||
},
|
||||
{
|
||||
to: (context: any) => context.serviceRefs.activityLog,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {isSignedInResult} from '../../shared/CloudBackupAndRestoreUtils';
|
||||
import {ErrorMessage, Issuers, OIDCErrors} from '../../shared/openId4VCI/Utils';
|
||||
import {ErrorMessage, OIDCErrors} from '../../shared/openId4VCI/Utils';
|
||||
import {isHardwareKeystoreExists} from '../../shared/cryptoutil/cryptoUtil';
|
||||
import {BiometricCancellationError} from '../../shared/error/BiometricCancellationError';
|
||||
import {NETWORK_REQUEST_FAILED, REQUEST_TIMEOUT} from '../../shared/constants';
|
||||
import {NETWORK_REQUEST_FAILED} from '../../shared/constants';
|
||||
import {VerificationErrorType} from '../../shared/vcjs/verifyCredential';
|
||||
|
||||
export const IssuersGuards = () => {
|
||||
@@ -12,9 +12,6 @@ export const IssuersGuards = () => {
|
||||
isSignedIn: (_: any, event: any) =>
|
||||
(event.data as isSignedInResult).isSignedIn,
|
||||
hasKeyPair: (context: any) => !!context.publicKey,
|
||||
isMultipleCredentialsSupported: (context: any, event: any) =>
|
||||
event.data.supportedCredentials.length > 1 &&
|
||||
context.selectedIssuer.credential_issuer === Issuers.Sunbird,
|
||||
isInternetConnected: (_: any, event: any) => !!event.data.isConnected,
|
||||
isOIDCflowCancelled: (_: any, event: any) => {
|
||||
// iOS & Android have different error strings for user cancelled flow
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {EventFrom, send, sendParent} from 'xstate';
|
||||
import {log} from 'xstate/lib/actions';
|
||||
import {IssuersModel} from './IssuersModel';
|
||||
import {IssuersActions} from './IssuersActions';
|
||||
import {IssuersService} from './IssuersService';
|
||||
import {IssuersGuards} from './IssuersGuards';
|
||||
import {CredentialTypes} from '../VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
const model = IssuersModel;
|
||||
|
||||
@@ -106,8 +106,7 @@ export const IssuersMachine = model.createMachine(
|
||||
src: 'downloadCredentialTypes',
|
||||
onDone: [
|
||||
{
|
||||
actions: 'setCredentialTypes',
|
||||
cond: 'isMultipleCredentialsSupported',
|
||||
actions: 'setSupportedCredentialTypes',
|
||||
target: 'selectingCredentialType',
|
||||
},
|
||||
{
|
||||
@@ -126,10 +125,7 @@ export const IssuersMachine = model.createMachine(
|
||||
target: 'displayIssuers',
|
||||
},
|
||||
SELECTED_CREDENTIAL_TYPE: {
|
||||
actions: [
|
||||
(_, event) => console.log('>>>>> event', event),
|
||||
'setSelectedCredentialType',
|
||||
],
|
||||
actions: 'setSelectedCredentialType',
|
||||
target: 'checkInternet',
|
||||
},
|
||||
},
|
||||
@@ -413,9 +409,11 @@ export interface logoType {
|
||||
|
||||
export interface displayType {
|
||||
name: string;
|
||||
logo: logoType;
|
||||
language: string;
|
||||
locale: string;
|
||||
language: string;
|
||||
logo: logoType;
|
||||
background_color: string;
|
||||
text_color: string;
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
@@ -426,14 +424,12 @@ export interface issuerType {
|
||||
client_id: string;
|
||||
'.well-known': string;
|
||||
redirect_uri: string;
|
||||
scopes_supported: [string];
|
||||
additional_headers: object;
|
||||
authorization_endpoint: string;
|
||||
authorization_alias: string;
|
||||
token_endpoint: string;
|
||||
proxy_token_endpoint: string;
|
||||
credential_endpoint: string;
|
||||
credential_type: [string];
|
||||
credential_audience: string;
|
||||
display: [displayType];
|
||||
credentialTypes: [CredentialTypes];
|
||||
}
|
||||
|
||||
@@ -104,7 +104,6 @@ export interface Typegen0 {
|
||||
| 'sendErrorEndEvent'
|
||||
| 'sendImpressionEvent'
|
||||
| 'sendSuccessEndEvent'
|
||||
| 'setCredentialTypes'
|
||||
| 'setCredentialWrapper'
|
||||
| 'setError'
|
||||
| 'setIsVerified'
|
||||
@@ -120,6 +119,7 @@ export interface Typegen0 {
|
||||
| 'setSelectedCredentialType'
|
||||
| 'setSelectedIssuerId'
|
||||
| 'setSelectedIssuers'
|
||||
| 'setSupportedCredentialTypes'
|
||||
| 'setTokenResponse'
|
||||
| 'setVCMetadata'
|
||||
| 'setVerifiableCredential'
|
||||
@@ -137,7 +137,6 @@ export interface Typegen0 {
|
||||
| 'isCustomSecureKeystore'
|
||||
| 'isGenericError'
|
||||
| 'isInternetConnected'
|
||||
| 'isMultipleCredentialsSupported'
|
||||
| 'isOIDCConfigError'
|
||||
| 'isOIDCflowCancelled'
|
||||
| 'isSignedIn'
|
||||
@@ -186,7 +185,6 @@ export interface Typegen0 {
|
||||
sendErrorEndEvent: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
sendImpressionEvent: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
sendSuccessEndEvent: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
setCredentialTypes: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
|
||||
setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
|
||||
setError:
|
||||
| 'error.platform.issuersMachine.displayIssuers:invocation[0]'
|
||||
@@ -216,6 +214,7 @@ export interface Typegen0 {
|
||||
setSelectedCredentialType: 'SELECTED_CREDENTIAL_TYPE';
|
||||
setSelectedIssuerId: 'SELECTED_ISSUER';
|
||||
setSelectedIssuers: 'done.invoke.issuersMachine.downloadIssuerConfig:invocation[0]';
|
||||
setSupportedCredentialTypes: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
|
||||
setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
|
||||
setVCMetadata:
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
@@ -244,7 +243,6 @@ export interface Typegen0 {
|
||||
isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
|
||||
isGenericError: 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
isInternetConnected: 'done.invoke.checkInternet';
|
||||
isMultipleCredentialsSupported: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
|
||||
isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
|
||||
isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
|
||||
isSignedIn: 'done.invoke.issuersMachine.storing:invocation[0]';
|
||||
|
||||
@@ -20,7 +20,7 @@ export const IssuersModel = createModel(
|
||||
loadingReason: 'displayIssuers' as string,
|
||||
verifiableCredential: null as VerifiableCredential | null,
|
||||
selectedCredentialType: {} as CredentialTypes,
|
||||
credentialTypes: [] as CredentialTypes[],
|
||||
supportedCredentialTypes: [] as CredentialTypes[],
|
||||
credentialWrapper: {} as CredentialWrapper,
|
||||
serviceRefs: {} as AppServices,
|
||||
verificationErrorMessage: '',
|
||||
|
||||
@@ -54,6 +54,6 @@ export function selectSelectingCredentialType(state: State) {
|
||||
return state.matches('selectingCredentialType');
|
||||
}
|
||||
|
||||
export function selectCredentialTypes(state: State) {
|
||||
return state.context.credentialTypes;
|
||||
export function selectSupportedCredentialTypes(state: State) {
|
||||
return state.context.supportedCredentialTypes;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import Cloud from '../../shared/CloudBackupAndRestoreUtils';
|
||||
import {API_URLS, CACHED_API} from '../../shared/api';
|
||||
import {CACHED_API} from '../../shared/api';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import {request} from '../../shared/request';
|
||||
import {
|
||||
constructAuthorizationConfiguration,
|
||||
constructProofJWT,
|
||||
getCredentialType,
|
||||
Issuers,
|
||||
Issuers_Key_Ref,
|
||||
updateCredentialInformation,
|
||||
vcDownloadTimeout,
|
||||
@@ -17,7 +14,6 @@ import {
|
||||
isHardwareKeystoreExists,
|
||||
} from '../../shared/cryptoutil/cryptoUtil';
|
||||
import {NativeModules} from 'react-native';
|
||||
import {getVCMetadata, VCMetadata} from '../../shared/VCMetadata';
|
||||
import {
|
||||
VerificationErrorType,
|
||||
verifyCredential,
|
||||
@@ -27,6 +23,7 @@ import {
|
||||
sendImpressionEvent,
|
||||
} from '../../shared/telemetry/TelemetryUtils';
|
||||
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
|
||||
import {isMosipVC} from '../../shared/Utils';
|
||||
import {VciClient} from '../../shared/vciClient/VciClient';
|
||||
|
||||
const {RNSecureKeystoreModule} = NativeModules;
|
||||
@@ -43,20 +40,18 @@ export const IssuersService = () => {
|
||||
let issuersConfig = await CACHED_API.fetchIssuerConfig(
|
||||
context.selectedIssuerId,
|
||||
);
|
||||
if (context.selectedIssuer['.well-known']) {
|
||||
await CACHED_API.fetchIssuerWellknownConfig(
|
||||
context.selectedIssuerId,
|
||||
context.selectedIssuer['.well-known'],
|
||||
);
|
||||
}
|
||||
const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig(
|
||||
context.selectedIssuerId,
|
||||
issuersConfig['.well-known'],
|
||||
);
|
||||
issuersConfig.credential_endpoint =
|
||||
wellknownResponse?.credential_endpoint;
|
||||
issuersConfig.credential_audience = wellknownResponse?.credential_issuer;
|
||||
issuersConfig.credentialTypes = wellknownResponse?.credentials_supported;
|
||||
return issuersConfig;
|
||||
},
|
||||
downloadCredentialTypes: async (context: any) => {
|
||||
const response = await request(
|
||||
API_URLS.credentialTypes.method,
|
||||
API_URLS.credentialTypes.buildURL(context.selectedIssuerId),
|
||||
);
|
||||
return response?.response;
|
||||
return context.selectedIssuer.credentialTypes;
|
||||
},
|
||||
downloadCredential: async (context: any) => {
|
||||
const downloadTimeout = await vcDownloadTimeout();
|
||||
@@ -65,7 +60,8 @@ export const IssuersService = () => {
|
||||
credentialAudience: context.selectedIssuer.credential_audience,
|
||||
credentialEndpoint: context.selectedIssuer.credential_endpoint,
|
||||
downloadTimeoutInMilliSeconds: downloadTimeout,
|
||||
credentialType: getCredentialType(context),
|
||||
credentialType: context.selectedCredentialType?.credential_definition
|
||||
.type ?? ['VerifiableCredential'],
|
||||
credentialFormat: 'ldp_vc',
|
||||
};
|
||||
const proofJWT = await constructProofJWT(
|
||||
@@ -81,8 +77,7 @@ export const IssuersService = () => {
|
||||
);
|
||||
|
||||
console.info(`VC download via ${context.selectedIssuerId} is successful`);
|
||||
credential = updateCredentialInformation(context, credential);
|
||||
return credential;
|
||||
return updateCredentialInformation(context, credential);
|
||||
},
|
||||
invokeAuthorization: async (context: any) => {
|
||||
sendImpressionEvent(
|
||||
@@ -92,16 +87,10 @@ export const IssuersService = () => {
|
||||
TelemetryConstants.Screens.webViewPage,
|
||||
),
|
||||
);
|
||||
let supportedScopes: [string];
|
||||
if (Object.keys(context.selectedCredentialType).length === 0) {
|
||||
supportedScopes = context.selectedIssuer.scopes_supported;
|
||||
} else {
|
||||
supportedScopes = [context.selectedCredentialType['scope']];
|
||||
}
|
||||
return await authorize(
|
||||
constructAuthorizationConfiguration(
|
||||
context.selectedIssuer,
|
||||
supportedScopes,
|
||||
context.selectedCredentialType.scope,
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -118,21 +107,19 @@ export const IssuersService = () => {
|
||||
},
|
||||
verifyCredential: async (context: any) => {
|
||||
//this issuer specific check has to be removed once vc validation is done.
|
||||
if (
|
||||
VCMetadata.fromVcMetadataString(getVCMetadata(context)).issuer ===
|
||||
Issuers.Sunbird
|
||||
) {
|
||||
if (isMosipVC(context.vcMetadata.issuer)) {
|
||||
const verificationResult = await verifyCredential(
|
||||
context.verifiableCredential?.credential,
|
||||
);
|
||||
if (!verificationResult.isVerified) {
|
||||
throw new Error(verificationResult.errorMessage);
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
isVerified: true,
|
||||
errorMessage: VerificationErrorType.NO_ERROR,
|
||||
};
|
||||
}
|
||||
const verificationResult = await verifyCredential(
|
||||
context.verifiableCredential?.credential,
|
||||
);
|
||||
if (!verificationResult.isVerified) {
|
||||
throw new Error(verificationResult.errorMessage);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import {StateFrom} from 'xstate';
|
||||
import {getMosipLogo} from '../../components/VC/common/VCUtils';
|
||||
import {VCMetadata} from '../../shared/VCMetadata';
|
||||
import {qrLoginMachine} from './QrLoginMachine';
|
||||
import {Credential} from '../VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
type State = StateFrom<typeof qrLoginMachine>;
|
||||
|
||||
@@ -57,31 +58,29 @@ export function selectIsVerifyingSuccesful(state: State) {
|
||||
return state.matches('success');
|
||||
}
|
||||
|
||||
export function selectCredential(state: State) {
|
||||
return new VCMetadata(state.context.selectedVc?.vcMetadata).isFromOpenId4VCI()
|
||||
? state.context.selectedVc?.verifiableCredential?.credential
|
||||
: state.context.selectedVc?.credential;
|
||||
export function selectCredential(state: State): Credential {
|
||||
return (
|
||||
state.context.selectedVc?.verifiableCredential?.credential ||
|
||||
state.context.selectedVc?.credential
|
||||
);
|
||||
}
|
||||
|
||||
export function selectVerifiableCredentialData(state: State) {
|
||||
const vcMetadata = new VCMetadata(state.context.selectedVc?.vcMetadata);
|
||||
return vcMetadata.isFromOpenId4VCI()
|
||||
? {
|
||||
vcMetadata: vcMetadata,
|
||||
face: state.context.selectedVc?.verifiableCredential?.credential
|
||||
?.credentialSubject?.face,
|
||||
issuerLogo: state.context.selectedVc?.verifiableCredential?.issuerLogo,
|
||||
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
||||
credentialTypes:
|
||||
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
||||
issuer: vcMetadata.issuer,
|
||||
}
|
||||
: {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
face: state.context.selectedVc?.credential?.biometrics?.face,
|
||||
issuerLogo: getMosipLogo(),
|
||||
};
|
||||
return {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
issuerLogo:
|
||||
state.context.selectedVc?.verifiableCredential?.issuerLogo ||
|
||||
getMosipLogo(),
|
||||
face:
|
||||
state.context.selectedVc?.verifiableCredential?.credential
|
||||
?.credentialSubject?.face ||
|
||||
state.context.selectedVc?.credential?.biometrics?.face,
|
||||
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
||||
credentialTypes:
|
||||
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
||||
};
|
||||
}
|
||||
|
||||
export function selectLinkTransactionResponse(state: State) {
|
||||
|
||||
@@ -2,17 +2,18 @@ import {assign, send} from 'xstate';
|
||||
import {CommunicationDetails} from '../../../shared/Utils';
|
||||
import {StoreEvents} from '../../store';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {MIMOTO_BASE_URL, MY_VCS_STORE_KEY} from '../../../shared/constants';
|
||||
import {
|
||||
API_CACHED_STORAGE_KEYS,
|
||||
MIMOTO_BASE_URL,
|
||||
MY_VCS_STORE_KEY,
|
||||
} from '../../../shared/constants';
|
||||
import {KeyPair} from 'react-native-rsa-native';
|
||||
import i18n from '../../../i18n';
|
||||
import {getHomeMachineService} from '../../../screens/Home/HomeScreenController';
|
||||
import {DownloadProps} from '../../../shared/api';
|
||||
import {isHardwareKeystoreExists} from '../../../shared/cryptoutil/cryptoUtil';
|
||||
import {getBindingCertificateConstant} from '../../../shared/keystore/SecureKeystore';
|
||||
import {
|
||||
getIdType,
|
||||
getVcVerificationDetails,
|
||||
} from '../../../shared/openId4VCI/Utils';
|
||||
import {getVcVerificationDetails} from '../../../shared/openId4VCI/Utils';
|
||||
import {TelemetryConstants} from '../../../shared/telemetry/TelemetryConstants';
|
||||
import {
|
||||
sendStartEvent,
|
||||
@@ -30,6 +31,7 @@ import {BackupEvents} from '../../backupAndRestore/backup';
|
||||
import {VcMetaEvents} from '../VCMetaMachine/VCMetaMachine';
|
||||
import {WalletBindingResponse} from '../VCMetaMachine/vc';
|
||||
import {BannerStatusType} from '../../../components/BannerNotification';
|
||||
import {getCredentialTypes} from '../../../components/VC/common/VCUtils';
|
||||
|
||||
export const VCItemActions = model => {
|
||||
return {
|
||||
@@ -61,6 +63,7 @@ export const VCItemActions = model => {
|
||||
statusType,
|
||||
context.vcMetadata,
|
||||
context.verifiableCredential,
|
||||
context.wellknownResponse,
|
||||
);
|
||||
},
|
||||
}),
|
||||
@@ -124,10 +127,11 @@ export const VCItemActions = model => {
|
||||
),
|
||||
|
||||
setContext: model.assign((context, event) => {
|
||||
const vcMetadata = context.vcMetadata;
|
||||
return {
|
||||
...context,
|
||||
...event.response,
|
||||
vcMetadata: context.vcMetadata,
|
||||
vcMetadata: VCMetadata.fromVC(vcMetadata),
|
||||
};
|
||||
}),
|
||||
storeContext: send(
|
||||
@@ -149,16 +153,22 @@ export const VCItemActions = model => {
|
||||
to: context => context.serviceRefs.store,
|
||||
},
|
||||
),
|
||||
|
||||
setVcMetadata: assign({
|
||||
vcMetadata: (_, event) => event.vcMetadata,
|
||||
}),
|
||||
|
||||
updateWellknownResponse: assign({
|
||||
wellknownResponse: (_, event) => event.data,
|
||||
}),
|
||||
|
||||
storeVcInContext: send(
|
||||
//todo : separate handling done for openid4vci , handle commonly from vc machine
|
||||
(context: any) => {
|
||||
const {serviceRefs, ...verifiableCredential} = context;
|
||||
const {serviceRefs, wellknownResponse, ...data} = context;
|
||||
return {
|
||||
type: 'VC_DOWNLOADED',
|
||||
vc: verifiableCredential,
|
||||
vc: data,
|
||||
vcMetadata: context.vcMetadata,
|
||||
};
|
||||
},
|
||||
@@ -442,7 +452,8 @@ export const VCItemActions = model => {
|
||||
_vcKey: context.vcMetadata.getVcKey(),
|
||||
type: 'VC_DOWNLOADED',
|
||||
id: context.vcMetadata.id,
|
||||
idType: getIdType(context.vcMetadata.issuer),
|
||||
issuer: context.vcMetadata.issuer!!,
|
||||
idType: getCredentialTypes(context.verifiableCredential),
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: data.id,
|
||||
@@ -453,47 +464,56 @@ export const VCItemActions = model => {
|
||||
},
|
||||
),
|
||||
logRemovedVc: send(
|
||||
(context: any, _) =>
|
||||
ActivityLogEvents.LOG_ACTIVITY({
|
||||
idType: getIdType(context.vcMetadata.issuer),
|
||||
id: context.vcMetadata.id,
|
||||
_vcKey: VCMetadata.fromVC(context.vcMetadata).getVcKey(),
|
||||
(context: any, _) => {
|
||||
const vcMetadata = VCMetadata.fromVC(context.vcMetadata);
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
idType: getCredentialTypes(context.verifiableCredential),
|
||||
issuer: vcMetadata.issuer!!,
|
||||
id: vcMetadata.id,
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: 'VC_REMOVED',
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: VCMetadata.fromVC(context.vcMetadata).id,
|
||||
}),
|
||||
vcLabel: vcMetadata.id,
|
||||
});
|
||||
},
|
||||
{
|
||||
to: context => context.serviceRefs.activityLog,
|
||||
},
|
||||
),
|
||||
logWalletBindingSuccess: send(
|
||||
(context: any) =>
|
||||
ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: VCMetadata.fromVC(context.vcMetadata).getVcKey(),
|
||||
(context: any) => {
|
||||
const vcMetadata = VCMetadata.fromVC(context.vcMetadata);
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: 'WALLET_BINDING_SUCCESSFULL',
|
||||
idType: getIdType(context.vcMetadata.issuer),
|
||||
id: context.vcMetadata.id,
|
||||
idType: getCredentialTypes(context.verifiableCredential),
|
||||
issuer: vcMetadata.issuer!!,
|
||||
id: vcMetadata.id,
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: VCMetadata.fromVC(context.vcMetadata).id,
|
||||
}),
|
||||
vcLabel: vcMetadata.id,
|
||||
});
|
||||
},
|
||||
{
|
||||
to: context => context.serviceRefs.activityLog,
|
||||
},
|
||||
),
|
||||
|
||||
logWalletBindingFailure: send(
|
||||
(context: any) =>
|
||||
ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: VCMetadata.fromVC(context.vcMetadata).getVcKey(),
|
||||
(context: any) => {
|
||||
const vcMetadata = VCMetadata.fromVC(context.vcMetadata);
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: 'WALLET_BINDING_FAILURE',
|
||||
id: context.vcMetadata.id,
|
||||
idType: getIdType(context.vcMetadata.issuer),
|
||||
id: vcMetadata.id,
|
||||
idType: getCredentialTypes(context.verifiableCredential),
|
||||
issuer: vcMetadata.issuer!!,
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: VCMetadata.fromVC(context.vcMetadata).id,
|
||||
}),
|
||||
vcLabel: vcMetadata.id,
|
||||
});
|
||||
},
|
||||
{
|
||||
to: context => context.serviceRefs.activityLog,
|
||||
},
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {VC} from '../VCMetaMachine/vc';
|
||||
|
||||
export const VCItemEvents = {
|
||||
DISMISS: () => ({}),
|
||||
CREDENTIAL_DOWNLOADED: (response: VC) => ({response}),
|
||||
STORE_RESPONSE: (response: VC) => ({response}),
|
||||
STORE_ERROR: (error: Error) => ({error}),
|
||||
POLL: () => ({}),
|
||||
DOWNLOAD_READY: () => ({}),
|
||||
FAILED: () => ({}),
|
||||
GET_VC_RESPONSE: (response: VC) => ({response}),
|
||||
INPUT_OTP: (OTP: string) => ({OTP}),
|
||||
RESEND_OTP: () => ({}),
|
||||
REFRESH: () => ({}),
|
||||
ADD_WALLET_BINDING_ID: () => ({}),
|
||||
CANCEL: () => ({}),
|
||||
CONFIRM: () => ({}),
|
||||
PIN_CARD: () => ({}),
|
||||
KEBAB_POPUP: () => ({}),
|
||||
SHOW_ACTIVITY: () => ({}),
|
||||
CLOSE_VC_MODAL: () => ({}),
|
||||
REMOVE: (vcMetadata: VCMetadata) => ({vcMetadata}),
|
||||
UPDATE_VC_METADATA: (vcMetadata: VCMetadata) => ({vcMetadata}),
|
||||
TAMPERED_VC: (key: string) => ({key}),
|
||||
SHOW_BINDING_STATUS: () => ({}),
|
||||
VERIFY: () => ({}),
|
||||
SET_VERIFICATION_STATUS: (response: unknown) => ({response}),
|
||||
RESET_VERIFICATION_STATUS: () => ({}),
|
||||
REMOVE_VERIFICATION_STATUS_BANNER: () => ({}),
|
||||
SHOW_VERIFICATION_STATUS_BANNER: (response: unknown) => ({response}),
|
||||
};
|
||||
@@ -4,9 +4,16 @@ import {VerificationErrorType} from '../../../shared/vcjs/verifyCredential';
|
||||
|
||||
export const VCItemGaurds = () => {
|
||||
return {
|
||||
hasCredentialAndWellknown: (context, event) => {
|
||||
const vc = event.response;
|
||||
return (
|
||||
vc?.verifiableCredential != null &&
|
||||
!!context.verifiableCredential?.wellKnown
|
||||
);
|
||||
},
|
||||
hasCredential: (_, event) => {
|
||||
const vc = event.response;
|
||||
return vc?.credential != null || vc?.verifiableCredential != null;
|
||||
return vc?.verifiableCredential != null;
|
||||
},
|
||||
isSignedIn: (_context, event) =>
|
||||
(event.data as isSignedInResult).isSignedIn,
|
||||
|
||||
@@ -44,6 +44,11 @@ export const VCItemMachine = model.createMachine(
|
||||
description: 'Fetch the VC data from the Memory.',
|
||||
on: {
|
||||
GET_VC_RESPONSE: [
|
||||
{
|
||||
actions: ['setContext'],
|
||||
cond: 'hasCredentialAndWellknown',
|
||||
target: '.fetchWellknown',
|
||||
},
|
||||
{
|
||||
actions: ['setContext'],
|
||||
cond: 'hasCredential',
|
||||
@@ -58,6 +63,20 @@ export const VCItemMachine = model.createMachine(
|
||||
target: '#vc-item-machine.vcUtilitiesState.idle',
|
||||
},
|
||||
},
|
||||
initial: 'idle',
|
||||
states: {
|
||||
idle: {},
|
||||
fetchWellknown: {
|
||||
invoke: {
|
||||
src: 'fetchIssuerWellknown',
|
||||
onDone: {
|
||||
actions: 'updateWellknownResponse',
|
||||
|
||||
target: `#vc-item-machine.vcUtilitiesState.idle`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
loadVcFromServer: {
|
||||
description:
|
||||
@@ -492,10 +511,10 @@ export const VCItemMachine = model.createMachine(
|
||||
{
|
||||
cond: 'isSignedIn',
|
||||
actions: ['sendBackupEvent'],
|
||||
target: '#vc-item-machine.vcUtilitiesState.idle',
|
||||
target: `#vc-item-machine.vcUtilitiesState.idle`,
|
||||
},
|
||||
{
|
||||
target: '#vc-item-machine.vcUtilitiesState.idle',
|
||||
target: `#vc-item-machine.vcUtilitiesState.idle`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -19,6 +19,11 @@ export interface Typegen0 {
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]': {
|
||||
type: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]': {
|
||||
type: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
||||
data: unknown;
|
||||
@@ -120,6 +125,7 @@ export interface Typegen0 {
|
||||
checkDownloadExpiryLimit: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
||||
checkStatus: 'done.invoke.checkStatus';
|
||||
downloadCredential: 'done.invoke.downloadCredential';
|
||||
fetchIssuerWellknown: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]';
|
||||
generateKeyPair: 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]';
|
||||
isUserSignedAlready:
|
||||
| 'done.invoke.vc-item-machine.vcUtilitiesState.kebabPopUp.triggerAutoBackup:invocation[0]'
|
||||
@@ -186,10 +192,12 @@ export interface Typegen0 {
|
||||
| 'unSetBindingTransactionId'
|
||||
| 'unSetError'
|
||||
| 'unSetOTP'
|
||||
| 'updateVcMetadata';
|
||||
| 'updateVcMetadata'
|
||||
| 'updateWellknownResponse';
|
||||
delays: never;
|
||||
guards:
|
||||
| 'hasCredential'
|
||||
| 'hasCredentialAndWellknown'
|
||||
| 'isCustomSecureKeystore'
|
||||
| 'isDownloadAllowed'
|
||||
| 'isSignedIn'
|
||||
@@ -199,6 +207,7 @@ export interface Typegen0 {
|
||||
| 'checkDownloadExpiryLimit'
|
||||
| 'checkStatus'
|
||||
| 'downloadCredential'
|
||||
| 'fetchIssuerWellknown'
|
||||
| 'generateKeyPair'
|
||||
| 'isUserSignedAlready'
|
||||
| 'loadDownloadLimitConfig'
|
||||
@@ -334,10 +343,12 @@ export interface Typegen0 {
|
||||
| 'DISMISS'
|
||||
| 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.requestingBindingOTP:invocation[0]';
|
||||
updateVcMetadata: 'PIN_CARD' | 'STORE_RESPONSE';
|
||||
updateWellknownResponse: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
hasCredential: 'GET_VC_RESPONSE';
|
||||
hasCredentialAndWellknown: 'GET_VC_RESPONSE';
|
||||
isCustomSecureKeystore:
|
||||
| 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addKeyPair:invocation[0]'
|
||||
| 'done.invoke.vc-item-machine.vcUtilitiesState.walletBinding.addingWalletBindingId:invocation[0]';
|
||||
@@ -356,6 +367,7 @@ export interface Typegen0 {
|
||||
| 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
||||
checkStatus: 'done.invoke.vc-item-machine.vcUtilitiesState.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
||||
downloadCredential: 'DOWNLOAD_READY';
|
||||
fetchIssuerWellknown: 'GET_VC_RESPONSE';
|
||||
generateKeyPair: 'INPUT_OTP';
|
||||
isUserSignedAlready: 'STORE_RESPONSE';
|
||||
loadDownloadLimitConfig: 'GET_VC_RESPONSE' | 'STORE_ERROR';
|
||||
@@ -375,6 +387,8 @@ export interface Typegen0 {
|
||||
| 'vcUtilitiesState.kebabPopUp.triggerAutoBackup'
|
||||
| 'vcUtilitiesState.loadVc'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromContext'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromContext.fetchWellknown'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromContext.idle'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromServer'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromServer.checkingStatus'
|
||||
| 'vcUtilitiesState.loadVc.loadVcFromServer.downloadingCredential'
|
||||
@@ -421,6 +435,7 @@ export interface Typegen0 {
|
||||
| 'loadVcFromContext'
|
||||
| 'loadVcFromServer'
|
||||
| {
|
||||
loadVcFromContext?: 'fetchWellknown' | 'idle';
|
||||
loadVcFromServer?:
|
||||
| 'checkingStatus'
|
||||
| 'downloadingCredential'
|
||||
|
||||
@@ -1,17 +1,52 @@
|
||||
import {createModel} from 'xstate/lib/model';
|
||||
import {AppServices} from '../../../shared/GlobalContext';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {VerifiableCredential, WalletBindingResponse} from '../VCMetaMachine/vc';
|
||||
import {
|
||||
Credential,
|
||||
DecodedCredential,
|
||||
VC,
|
||||
WalletBindingResponse,
|
||||
} from '../VCMetaMachine/vc';
|
||||
import {CommunicationDetails} from '../../../shared/Utils';
|
||||
import {VCItemEvents} from './VCItemEvents';
|
||||
import {vcVerificationBannerDetails} from '../../../components/BannerNotificationContainer';
|
||||
|
||||
const VCItemEvents = {
|
||||
DISMISS: () => ({}),
|
||||
CREDENTIAL_DOWNLOADED: (response: VC) => ({response}),
|
||||
STORE_RESPONSE: (response: VC) => ({response}),
|
||||
STORE_ERROR: (error: Error) => ({error}),
|
||||
POLL: () => ({}),
|
||||
DOWNLOAD_READY: () => ({}),
|
||||
FAILED: () => ({}),
|
||||
GET_VC_RESPONSE: (response: VC) => ({response}),
|
||||
INPUT_OTP: (OTP: string) => ({OTP}),
|
||||
RESEND_OTP: () => ({}),
|
||||
REFRESH: () => ({}),
|
||||
ADD_WALLET_BINDING_ID: () => ({}),
|
||||
CANCEL: () => ({}),
|
||||
CONFIRM: () => ({}),
|
||||
PIN_CARD: () => ({}),
|
||||
KEBAB_POPUP: () => ({}),
|
||||
SHOW_ACTIVITY: () => ({}),
|
||||
CLOSE_VC_MODAL: () => ({}),
|
||||
REMOVE: (vcMetadata: VCMetadata) => ({vcMetadata}),
|
||||
UPDATE_VC_METADATA: (vcMetadata: VCMetadata) => ({vcMetadata}),
|
||||
TAMPERED_VC: (key: string) => ({key}),
|
||||
SHOW_BINDING_STATUS: () => ({}),
|
||||
VERIFY: () => ({}),
|
||||
SET_VERIFICATION_STATUS: (response: unknown) => ({response}),
|
||||
RESET_VERIFICATION_STATUS: () => ({}),
|
||||
REMOVE_VERIFICATION_STATUS_BANNER: () => ({}),
|
||||
SHOW_VERIFICATION_STATUS_BANNER: (response: unknown) => ({response}),
|
||||
};
|
||||
|
||||
export const VCItemModel = createModel(
|
||||
{
|
||||
serviceRefs: {} as AppServices,
|
||||
vcMetadata: {} as VCMetadata,
|
||||
generatedOn: new Date() as Date,
|
||||
verifiableCredential: null as unknown as VerifiableCredential,
|
||||
credential: null as unknown as DecodedCredential,
|
||||
verifiableCredential: null as unknown as Credential,
|
||||
hashedId: '',
|
||||
publicKey: '',
|
||||
privateKey: '',
|
||||
@@ -27,6 +62,7 @@ export const VCItemModel = createModel(
|
||||
communicationDetails: null as unknown as CommunicationDetails,
|
||||
verificationStatus: null as vcVerificationBannerDetails | null,
|
||||
showVerificationStatusBanner: false as boolean,
|
||||
wellknownResponse: {} as Object,
|
||||
},
|
||||
{
|
||||
events: VCItemEvents,
|
||||
|
||||
@@ -2,6 +2,11 @@ import {StateFrom} from 'xstate';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {VCItemMachine} from './VCItemMachine';
|
||||
import {getMosipLogo} from '../../../components/VC/common/VCUtils';
|
||||
import {
|
||||
Credential,
|
||||
VerifiableCredential,
|
||||
VerifiableCredentialData,
|
||||
} from '../VCMetaMachine/vc';
|
||||
|
||||
type State = StateFrom<typeof VCItemMachine>;
|
||||
|
||||
@@ -26,39 +31,31 @@ export function selectVerifiableCredential(state: State) {
|
||||
}
|
||||
|
||||
export function getVerifiableCredential(
|
||||
vcMetadata: VCMetadata,
|
||||
verifiableCredential,
|
||||
) {
|
||||
return VCMetadata.fromVC(vcMetadata).isFromOpenId4VCI()
|
||||
? verifiableCredential?.credential
|
||||
: verifiableCredential;
|
||||
verifiableCredential: VerifiableCredential | Credential,
|
||||
): Credential {
|
||||
return verifiableCredential?.credential || verifiableCredential;
|
||||
}
|
||||
|
||||
export function selectCredential(state: State) {
|
||||
return getVerifiableCredential(
|
||||
state.context.vcMetadata,
|
||||
state.context.verifiableCredential,
|
||||
);
|
||||
export function selectCredential(state: State): Credential {
|
||||
return getVerifiableCredential(state.context.verifiableCredential);
|
||||
}
|
||||
|
||||
export function selectVerifiableCredentialData(state: State) {
|
||||
export function selectVerifiableCredentialData(
|
||||
state: State,
|
||||
): VerifiableCredentialData {
|
||||
const vcMetadata = new VCMetadata(state.context.vcMetadata);
|
||||
return vcMetadata.isFromOpenId4VCI()
|
||||
? {
|
||||
vcMetadata: vcMetadata,
|
||||
face: state.context.verifiableCredential?.credential?.credentialSubject
|
||||
.face,
|
||||
issuerLogo: state.context.verifiableCredential?.issuerLogo,
|
||||
wellKnown: state.context.verifiableCredential?.wellKnown,
|
||||
credentialTypes: state.context.verifiableCredential?.credentialTypes,
|
||||
issuer: vcMetadata.issuer,
|
||||
}
|
||||
: {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
face: state.context.credential?.biometrics?.face,
|
||||
issuerLogo: getMosipLogo(),
|
||||
};
|
||||
|
||||
return {
|
||||
vcMetadata: vcMetadata,
|
||||
face:
|
||||
state.context.verifiableCredential?.credential?.credentialSubject?.face ??
|
||||
state.context.credential?.biometrics?.face,
|
||||
issuerLogo:
|
||||
state.context.verifiableCredential?.issuerLogo ?? getMosipLogo(),
|
||||
wellKnown: state.context.verifiableCredential?.wellKnown,
|
||||
credentialTypes: state.context.verifiableCredential?.credentialTypes,
|
||||
issuer: vcMetadata.issuer,
|
||||
};
|
||||
}
|
||||
|
||||
export function selectKebabPopUp(state: State) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import Cloud from '../../../shared/CloudBackupAndRestoreUtils';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import getAllConfigurations, {
|
||||
API_URLS,
|
||||
CACHED_API,
|
||||
DownloadProps,
|
||||
} from '../../../shared/api';
|
||||
import {
|
||||
@@ -16,8 +17,9 @@ import {
|
||||
import {CredentialDownloadResponse, request} from '../../../shared/request';
|
||||
import {WalletBindingResponse} from '../VCMetaMachine/vc';
|
||||
import {verifyCredential} from '../../../shared/vcjs/verifyCredential';
|
||||
import {getMosipIdentifier} from '../../../shared/commonUtil';
|
||||
import {getVerifiableCredential} from './VCItemSelectors';
|
||||
import {getSelectedCredentialTypeDetails} from '../../../shared/openId4VCI/Utils';
|
||||
import {getCredentialTypes} from '../../../components/VC/common/VCUtils';
|
||||
|
||||
const {RNSecureKeystoreModule} = NativeModules;
|
||||
export const VCItemServices = model => {
|
||||
@@ -105,9 +107,7 @@ export const VCItemServices = model => {
|
||||
);
|
||||
},
|
||||
requestBindingOTP: async context => {
|
||||
const vc = VCMetadata.fromVC(context.vcMetadata).isFromOpenId4VCI()
|
||||
? context.verifiableCredential.credential
|
||||
: context.verifiableCredential;
|
||||
const vc = getVerifiableCredential(context.verifiableCredential);
|
||||
const response = await request(
|
||||
API_URLS.bindingOtp.method,
|
||||
API_URLS.bindingOtp.buildURL(),
|
||||
@@ -124,6 +124,18 @@ export const VCItemServices = model => {
|
||||
}
|
||||
return response;
|
||||
},
|
||||
fetchIssuerWellknown: async context => {
|
||||
const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig(
|
||||
context.vcMetadata.issuer,
|
||||
context.verifiableCredential.wellKnown,
|
||||
true,
|
||||
);
|
||||
const wellknownOfCredential = getSelectedCredentialTypeDetails(
|
||||
wellknownResponse,
|
||||
getCredentialTypes(context.verifiableCredential),
|
||||
);
|
||||
return wellknownOfCredential;
|
||||
},
|
||||
checkStatus: context => (callback, onReceive) => {
|
||||
const pollInterval = setInterval(
|
||||
() => callback(model.events.POLL()),
|
||||
@@ -199,10 +211,7 @@ export const VCItemServices = model => {
|
||||
verifyCredential: async context => {
|
||||
if (context.verifiableCredential) {
|
||||
const verificationResult = await verifyCredential(
|
||||
getVerifiableCredential(
|
||||
context.vcMetadata,
|
||||
context.verifiableCredential,
|
||||
),
|
||||
getVerifiableCredential(context.verifiableCredential),
|
||||
);
|
||||
if (!verificationResult.isVerified) {
|
||||
throw new Error(verificationResult.errorMessage);
|
||||
|
||||
@@ -15,7 +15,6 @@ export function selectMyVcsMetadata(state: State): VCMetadata[] {
|
||||
export function selectShareableVcsMetadata(state: State): VCMetadata[] {
|
||||
return state.context.myVcsMetadata.filter(
|
||||
vcMetadata =>
|
||||
state.context.myVcs[vcMetadata.getVcKey()]?.credential != null ||
|
||||
state.context.myVcs[vcMetadata.getVcKey()]?.verifiableCredential != null,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import {displayType, logoType} from '../../Issuers/IssuersMachine';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
|
||||
export interface VC {
|
||||
id?: string;
|
||||
idType?: VcIdType;
|
||||
credential?: DecodedCredential;
|
||||
verifiableCredential: VerifiableCredential;
|
||||
verifiableCredential: VerifiableCredential | Credential;
|
||||
requestId?: string;
|
||||
isVerified?: boolean;
|
||||
lastVerifiedOn: number;
|
||||
walletBindingResponse?: WalletBindingResponse;
|
||||
hashedId?: string;
|
||||
vcMetadata: VCMetadata;
|
||||
}
|
||||
|
||||
export type VcIdType = 'UIN' | 'VID';
|
||||
@@ -54,7 +56,8 @@ export interface Credential {
|
||||
type: 'RsaSignature2018' | string;
|
||||
verificationMethod: string;
|
||||
};
|
||||
type: VerifiableCredentialType[];
|
||||
type: string[];
|
||||
credentialTypes: string[];
|
||||
}
|
||||
|
||||
export interface VerifiableCredential {
|
||||
@@ -65,11 +68,20 @@ export interface VerifiableCredential {
|
||||
credentialTypes: Object[];
|
||||
}
|
||||
|
||||
export interface VerifiableCredentialData {
|
||||
vcMetadata: VCMetadata;
|
||||
face: string;
|
||||
issuerLogo: logoType;
|
||||
wellKnown?: string;
|
||||
credentialTypes?: Object[];
|
||||
issuer?: string;
|
||||
}
|
||||
|
||||
export interface CredentialWrapper {
|
||||
verifiableCredential: VerifiableCredential;
|
||||
identifier: string;
|
||||
generatedOn: Date;
|
||||
issuerLogo: string;
|
||||
vcMetadata: VCMetadata;
|
||||
}
|
||||
|
||||
export interface CredentialTypes {
|
||||
@@ -84,10 +96,11 @@ export interface CredentialTypes {
|
||||
};
|
||||
}
|
||||
|
||||
export type VerifiableCredentialType =
|
||||
| 'VerifiableCredential'
|
||||
| 'MOSIPVerfiableCredential'
|
||||
| string;
|
||||
export interface IssuerWellknownResponse {
|
||||
credential_issuer: string;
|
||||
credential_endpoint: string;
|
||||
credentials_supported: Object[];
|
||||
}
|
||||
|
||||
export interface VCLabel {
|
||||
singular: string;
|
||||
@@ -116,3 +129,16 @@ export interface WalletBindingResponse {
|
||||
thumbprint: string;
|
||||
expireDateTime: string;
|
||||
}
|
||||
|
||||
//TODO: Check if Type word is needed in the naming
|
||||
export interface VCMetadataType {
|
||||
//TODO: requestId is not null at any point as its used for file names and all
|
||||
isPinned: boolean;
|
||||
requestId: string | null;
|
||||
issuer: string;
|
||||
protocol: string;
|
||||
id: string;
|
||||
timestamp: string;
|
||||
isVerified: boolean;
|
||||
credentialType: string;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,15 @@ const model = createModel(
|
||||
{
|
||||
serviceRefs: {} as AppServices,
|
||||
activities: [] as ActivityLog[],
|
||||
wellKnownIssuerMap: {} as Record<string, Object>,
|
||||
},
|
||||
{
|
||||
events: {
|
||||
STORE_RESPONSE: (response: unknown) => ({response}),
|
||||
LOG_ACTIVITY: (log: ActivityLog | ActivityLog[]) => ({log}),
|
||||
LOG_ACTIVITY: (log: ActivityLog | ActivityLog[], wellknown?: any) => ({
|
||||
log,
|
||||
wellknown,
|
||||
}),
|
||||
REFRESH: () => ({}),
|
||||
},
|
||||
},
|
||||
@@ -40,6 +44,15 @@ export const activityLogMachine =
|
||||
on: {
|
||||
STORE_RESPONSE: {
|
||||
actions: ['setActivities', sendParent('READY')],
|
||||
target: 'loadWellknownConfig',
|
||||
},
|
||||
},
|
||||
},
|
||||
loadWellknownConfig: {
|
||||
entry: 'fetchAllWellKnownConfigResponse',
|
||||
on: {
|
||||
STORE_RESPONSE: {
|
||||
actions: ['setAllWellknownConfigResponse'],
|
||||
target: 'ready',
|
||||
},
|
||||
},
|
||||
@@ -58,7 +71,7 @@ export const activityLogMachine =
|
||||
},
|
||||
},
|
||||
logging: {
|
||||
entry: 'storeActivity',
|
||||
entry: ['loadWellknownIntoContext', 'storeActivity'],
|
||||
on: {
|
||||
STORE_RESPONSE: {
|
||||
actions: 'prependActivity',
|
||||
@@ -94,11 +107,41 @@ export const activityLogMachine =
|
||||
{to: context => context.serviceRefs.store},
|
||||
),
|
||||
|
||||
loadWellknownIntoContext: model.assign({
|
||||
wellKnownIssuerMap: (context, event) => {
|
||||
if (!!event.wellknown) {
|
||||
const updatedWellKnownIssuerMap = {
|
||||
...context.wellKnownIssuerMap,
|
||||
};
|
||||
updatedWellKnownIssuerMap[event.log.issuer] = event.wellknown;
|
||||
return updatedWellKnownIssuerMap as unknown as Record<
|
||||
string,
|
||||
Object
|
||||
>;
|
||||
}
|
||||
return context.wellKnownIssuerMap;
|
||||
},
|
||||
}),
|
||||
|
||||
prependActivity: model.assign({
|
||||
activities: (context, event) =>
|
||||
(Array.isArray(event.response)
|
||||
? [...event.response, ...context.activities]
|
||||
: [event.response, ...context.activities]) as ActivityLog[],
|
||||
activities: (context, event) => {
|
||||
return (
|
||||
Array.isArray(event.response)
|
||||
? [...event.response, ...context.activities]
|
||||
: [event.response, ...context.activities]
|
||||
) as ActivityLog[];
|
||||
},
|
||||
}),
|
||||
|
||||
fetchAllWellKnownConfigResponse: send(
|
||||
() => StoreEvents.FETCH_ALL_WELLKNOWN_CONFIG(),
|
||||
{to: context => context.serviceRefs.store},
|
||||
),
|
||||
|
||||
setAllWellknownConfigResponse: model.assign({
|
||||
wellKnownIssuerMap: (_, event) => {
|
||||
return event.response as Record<string, Object>;
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
@@ -134,6 +177,10 @@ export function selectActivities(state: State) {
|
||||
return state.context.activities;
|
||||
}
|
||||
|
||||
export function selectWellknownIssuerMap(state: State) {
|
||||
return state.context.wellKnownIssuerMap;
|
||||
}
|
||||
|
||||
export function selectIsRefreshing(state: State) {
|
||||
return state.matches('ready.refreshing');
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"loadActivities": "REFRESH" | "xstate.init";
|
||||
"prependActivity": "STORE_RESPONSE";
|
||||
"setActivities": "STORE_RESPONSE";
|
||||
"storeActivity": "LOG_ACTIVITY";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
|
||||
};
|
||||
eventsCausingServices: {
|
||||
|
||||
};
|
||||
matchesStates: "init" | "ready" | "ready.idle" | "ready.logging" | "ready.refreshing" | { "ready"?: "idle" | "logging" | "refreshing"; };
|
||||
tags: never;
|
||||
}
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
fetchAllWellKnownConfigResponse: 'STORE_RESPONSE';
|
||||
loadActivities: 'REFRESH' | 'xstate.init';
|
||||
loadWellknownIntoContext: 'LOG_ACTIVITY';
|
||||
prependActivity: 'STORE_RESPONSE';
|
||||
setActivities: 'STORE_RESPONSE';
|
||||
setAllWellknownConfigResponse: 'STORE_RESPONSE';
|
||||
storeActivity: 'LOG_ACTIVITY';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {};
|
||||
eventsCausingServices: {};
|
||||
matchesStates:
|
||||
| 'init'
|
||||
| 'loadWellknownConfig'
|
||||
| 'ready'
|
||||
| 'ready.idle'
|
||||
| 'ready.logging'
|
||||
| 'ready.refreshing'
|
||||
| {ready?: 'idle' | 'logging' | 'refreshing'};
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
sendStartEvent,
|
||||
} from '../../../shared/telemetry/TelemetryUtils';
|
||||
import {TelemetryConstants} from '../../../shared/telemetry/TelemetryConstants';
|
||||
import {getIdType} from '../../../shared/openId4VCI/Utils';
|
||||
import {getCredentialTypes} from '../../../components/VC/common/VCUtils';
|
||||
|
||||
const {verifier, EventTypes, VerificationStatus} = tuvali;
|
||||
|
||||
@@ -620,7 +620,10 @@ export const requestMachine =
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: context.receiveLogType,
|
||||
id: vcMetadata.id,
|
||||
idType: getIdType(vcMetadata.issuer),
|
||||
idType: getCredentialTypes(
|
||||
context.incomingVc.verifiableCredential,
|
||||
),
|
||||
issuer: vcMetadata.issuer!!,
|
||||
timestamp: Date.now(),
|
||||
deviceName:
|
||||
context.senderInfo.name || context.senderInfo.deviceName,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {StateFrom} from 'xstate';
|
||||
import {requestMachine} from './requestMachine';
|
||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
||||
import {getMosipLogo} from '../../../components/VC/common/VCUtils';
|
||||
import {Credential} from '../../VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
type State = StateFrom<typeof requestMachine>;
|
||||
|
||||
@@ -9,31 +10,29 @@ export function selectSenderInfo(state: State) {
|
||||
return state.context.senderInfo;
|
||||
}
|
||||
|
||||
export function selectCredential(state: State) {
|
||||
return new VCMetadata(state.context.incomingVc?.vcMetadata).isFromOpenId4VCI()
|
||||
? state.context.incomingVc?.verifiableCredential?.credential
|
||||
: state.context.incomingVc?.verifiableCredential;
|
||||
export function selectCredential(state: State): Credential {
|
||||
return (
|
||||
state.context.incomingVc?.verifiableCredential?.credential ||
|
||||
state.context.incomingVc?.verifiableCredential
|
||||
);
|
||||
}
|
||||
|
||||
export function selectVerifiableCredentialData(state: State) {
|
||||
const vcMetadata = new VCMetadata(state.context.incomingVc?.vcMetadata);
|
||||
return vcMetadata.isFromOpenId4VCI()
|
||||
? {
|
||||
vcMetadata: vcMetadata,
|
||||
face: state.context.incomingVc?.verifiableCredential.credential
|
||||
.credentialSubject.face,
|
||||
issuerLogo: state.context.incomingVc?.verifiableCredential?.issuerLogo,
|
||||
wellKnown: state.context.incomingVc?.verifiableCredential?.wellKnown,
|
||||
credentialTypes:
|
||||
state.context.incomingVc?.verifiableCredential?.credentialTypes,
|
||||
issuer: vcMetadata.issuer,
|
||||
}
|
||||
: {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
face: state.context.incomingVc?.credential?.biometrics?.face,
|
||||
issuerLogo: getMosipLogo(),
|
||||
};
|
||||
return {
|
||||
vcMetadata: vcMetadata,
|
||||
face:
|
||||
state.context.incomingVc?.verifiableCredential.credential
|
||||
?.credentialSubject?.face ||
|
||||
state.context.incomingVc?.credential?.biometrics?.face,
|
||||
issuerLogo:
|
||||
state.context.incomingVc?.verifiableCredential?.issuerLogo ||
|
||||
getMosipLogo(),
|
||||
issuer: vcMetadata.issuer,
|
||||
wellKnown: state.context.incomingVc?.verifiableCredential?.wellKnown,
|
||||
credentialTypes:
|
||||
state.context.incomingVc?.verifiableCredential?.credentialTypes,
|
||||
};
|
||||
}
|
||||
|
||||
export function selectIsReviewingInIdle(state: State) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
MY_VCS_STORE_KEY,
|
||||
MY_LOGIN_STORE_KEY,
|
||||
} from '../../../shared/constants';
|
||||
import {getIdType} from '../../../shared/openId4VCI/Utils';
|
||||
import {TelemetryConstants} from '../../../shared/telemetry/TelemetryConstants';
|
||||
import {
|
||||
sendImpressionEvent,
|
||||
@@ -30,6 +29,7 @@ import {StoreEvents} from '../../store';
|
||||
import tuvali from '@mosip/tuvali';
|
||||
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
|
||||
import {NativeModules} from 'react-native';
|
||||
import {getCredentialTypes} from '../../../components/VC/common/VCUtils';
|
||||
|
||||
const {wallet, EventTypes, VerificationStatus} = tuvali;
|
||||
export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
@@ -191,14 +191,16 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
|
||||
logShared: send(
|
||||
(context: any) => {
|
||||
const vcMetadata = context.selectedVc?.vcMetadata;
|
||||
const vcMetadata = VCMetadata.fromVC(context.selectedVc?.vcMetadata);
|
||||
const selectedVc = context.QrLoginRef.getSnapshot().context.selectedVc;
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: VCMetadata.fromVC(vcMetadata).getVcKey(),
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: context.shareLogType
|
||||
? context.shareLogType
|
||||
: 'VC_SHARED_WITH_VERIFICATION_CONSENT',
|
||||
id: vcMetadata.id,
|
||||
idType: getIdType(vcMetadata.issuer),
|
||||
idType: getCredentialTypes(selectedVc.verifiableCredential),
|
||||
issuer: vcMetadata.issuer!!,
|
||||
timestamp: Date.now(),
|
||||
deviceName:
|
||||
context.receiverInfo.name || context.receiverInfo.deviceName,
|
||||
@@ -209,17 +211,21 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
),
|
||||
|
||||
logFailedVerification: send(
|
||||
context =>
|
||||
ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: VCMetadata.fromVC(context.selectedVc).getVcKey(),
|
||||
context => {
|
||||
const vcMetadata = VCMetadata.fromVC(context.selectedVc);
|
||||
const selectedVc = context.QrLoginRef.getSnapshot().context.selectedVc;
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: vcMetadata.getVcKey(),
|
||||
type: 'PRESENCE_VERIFICATION_FAILED',
|
||||
timestamp: Date.now(),
|
||||
idType: getIdType(context.selectedVc.vcMetadata.issuer),
|
||||
id: context.selectedVc.vcMetadata.id,
|
||||
idType: getCredentialTypes(selectedVc.verifiableCredential),
|
||||
id: vcMetadata.id,
|
||||
issuer: vcMetadata.issuer!!,
|
||||
deviceName:
|
||||
context.receiverInfo.name || context.receiverInfo.deviceName,
|
||||
vcLabel: context.selectedVc.vcMetadata.id,
|
||||
}),
|
||||
vcLabel: vcMetadata.id,
|
||||
});
|
||||
},
|
||||
{to: context => context.serviceRefs.activityLog},
|
||||
),
|
||||
|
||||
@@ -242,11 +248,8 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
),
|
||||
loadVCDataToMemory: send(
|
||||
(context: any) => {
|
||||
let metadata = VCMetadata.fromVC(context.quickShareData?.meta);
|
||||
|
||||
let verifiableCredential = metadata.isFromOpenId4VCI()
|
||||
? {credential: context.quickShareData?.verifiableCredential}
|
||||
: context.quickShareData?.verifiableCredential;
|
||||
const verifiableCredential =
|
||||
context.quickShareData?.verifiableCredential;
|
||||
|
||||
return StoreEvents.SET(metadata.getVcKey(), {
|
||||
verifiableCredential: verifiableCredential,
|
||||
@@ -268,16 +271,22 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => {
|
||||
),
|
||||
|
||||
storingActivityLog: send(
|
||||
(_, event) =>
|
||||
ActivityLogEvents.LOG_ACTIVITY({
|
||||
(context, event) => {
|
||||
const vcMetadata = event.response.selectedVc.vcMetadata;
|
||||
|
||||
const selectedVc = context.QrLoginRef.getSnapshot().context.selectedVc;
|
||||
|
||||
return ActivityLogEvents.LOG_ACTIVITY({
|
||||
_vcKey: '',
|
||||
id: event.response.selectedVc.vcMetadata.id,
|
||||
idType: getIdType(event.response.selectedVc.vcMetadata.issuer),
|
||||
id: vcMetadata.id,
|
||||
issuer: vcMetadata.issuer!!,
|
||||
idType: getCredentialTypes(selectedVc.verifiableCredential),
|
||||
type: 'QRLOGIN_SUCCESFULL',
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
vcLabel: String(event.response.selectedVc.vcMetadata.id),
|
||||
}),
|
||||
vcLabel: String(vcMetadata.id),
|
||||
});
|
||||
},
|
||||
{
|
||||
to: (context: any) => context.serviceRefs.activityLog,
|
||||
},
|
||||
|
||||
@@ -18,30 +18,28 @@ export function selectVcName(state: State) {
|
||||
}
|
||||
|
||||
export function selectCredential(state: State) {
|
||||
return new VCMetadata(state.context.selectedVc?.vcMetadata).isFromOpenId4VCI()
|
||||
? state.context.selectedVc?.verifiableCredential?.credential
|
||||
: state.context.selectedVc?.verifiableCredential;
|
||||
return (
|
||||
state.context.selectedVc?.verifiableCredential?.credential ||
|
||||
state.context.selectedVc?.verifiableCredential
|
||||
);
|
||||
}
|
||||
|
||||
export function selectVerifiableCredentialData(state: State) {
|
||||
const vcMetadata = new VCMetadata(state.context.selectedVc?.vcMetadata);
|
||||
return vcMetadata.isFromOpenId4VCI()
|
||||
? {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
issuerLogo: state.context.selectedVc?.verifiableCredential?.issuerLogo,
|
||||
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
||||
face: state.context.selectedVc?.verifiableCredential?.credential
|
||||
.credentialSubject?.face,
|
||||
credentialTypes:
|
||||
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
||||
}
|
||||
: {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
face: state.context.selectedVc?.credential?.biometrics?.face,
|
||||
issuerLogo: getMosipLogo(),
|
||||
};
|
||||
return {
|
||||
vcMetadata: vcMetadata,
|
||||
issuer: vcMetadata.issuer,
|
||||
issuerLogo:
|
||||
state.context.selectedVc?.verifiableCredential?.issuerLogo ||
|
||||
getMosipLogo(),
|
||||
face:
|
||||
state.context.selectedVc?.verifiableCredential?.credential
|
||||
?.credentialSubject?.face ||
|
||||
state.context.selectedVc?.credential?.biometrics?.face,
|
||||
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
||||
credentialTypes:
|
||||
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
||||
};
|
||||
}
|
||||
|
||||
export function selectQrLoginRef(state: State) {
|
||||
|
||||
@@ -1,47 +1,71 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke.faceScanner.capturing:invocation[0]": { type: "done.invoke.faceScanner.capturing:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.faceScanner.verifying:invocation[0]": { type: "done.invoke.faceScanner.verifying:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform.faceScanner.capturing:invocation[0]": { type: "error.platform.faceScanner.capturing:invocation[0]"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"captureImage": "done.invoke.faceScanner.capturing:invocation[0]";
|
||||
"checkPermission": "done.invoke.faceScanner.init.checkingPermission:invocation[0]";
|
||||
"requestPermission": "done.invoke.faceScanner.init.requestingPermission:invocation[0]";
|
||||
"verifyImage": "done.invoke.faceScanner.verifying:invocation[0]";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"flipWhichCamera": "FLIP_CAMERA";
|
||||
"openSettings": "OPEN_SETTINGS";
|
||||
"setCameraRef": "READY";
|
||||
"setCaptureError": "error.platform.faceScanner.capturing:invocation[0]";
|
||||
"setCapturedImage": "done.invoke.faceScanner.capturing:invocation[0]";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"canRequestPermission": "DENIED";
|
||||
"doesFaceMatch": "done.invoke.faceScanner.verifying:invocation[0]";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"captureImage": "CAPTURE";
|
||||
"checkPermission": "APP_FOCUSED" | "xstate.init";
|
||||
"requestPermission": "DENIED";
|
||||
"verifyImage": "done.invoke.faceScanner.capturing:invocation[0]";
|
||||
};
|
||||
matchesStates: "capturing" | "init" | "init.checkingPermission" | "init.permissionDenied" | "init.permissionGranted" | "init.requestingPermission" | "invalid" | "scanning" | "valid" | "verifying" | { "init"?: "checkingPermission" | "permissionDenied" | "permissionGranted" | "requestingPermission"; };
|
||||
tags: never;
|
||||
}
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.faceScanner.capturing:invocation[0]': {
|
||||
type: 'done.invoke.faceScanner.capturing:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.faceScanner.verifying:invocation[0]': {
|
||||
type: 'done.invoke.faceScanner.verifying:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.faceScanner.capturing:invocation[0]': {
|
||||
type: 'error.platform.faceScanner.capturing:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
captureImage: 'done.invoke.faceScanner.capturing:invocation[0]';
|
||||
checkPermission: 'done.invoke.faceScanner.init.checkingPermission:invocation[0]';
|
||||
requestPermission: 'done.invoke.faceScanner.init.requestingPermission:invocation[0]';
|
||||
verifyImage: 'done.invoke.faceScanner.verifying:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
flipWhichCamera: 'FLIP_CAMERA';
|
||||
openSettings: 'OPEN_SETTINGS';
|
||||
setCameraRef: 'READY';
|
||||
setCaptureError: 'error.platform.faceScanner.capturing:invocation[0]';
|
||||
setCapturedImage: 'done.invoke.faceScanner.capturing:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
canRequestPermission: 'DENIED';
|
||||
doesFaceMatch: 'done.invoke.faceScanner.verifying:invocation[0]';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
captureImage: 'CAPTURE';
|
||||
checkPermission: 'APP_FOCUSED' | 'xstate.init';
|
||||
requestPermission: 'DENIED';
|
||||
verifyImage: 'done.invoke.faceScanner.capturing:invocation[0]';
|
||||
};
|
||||
matchesStates:
|
||||
| 'capturing'
|
||||
| 'init'
|
||||
| 'init.checkingPermission'
|
||||
| 'init.permissionDenied'
|
||||
| 'init.permissionGranted'
|
||||
| 'init.requestingPermission'
|
||||
| 'invalid'
|
||||
| 'scanning'
|
||||
| 'valid'
|
||||
| 'verifying'
|
||||
| {
|
||||
init?:
|
||||
| 'checkingPermission'
|
||||
| 'permissionDenied'
|
||||
| 'permissionGranted'
|
||||
| 'requestingPermission';
|
||||
};
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -390,4 +390,4 @@ export function selectIsPasscodeUnlock(state: State) {
|
||||
return (
|
||||
state.context.isBiometricToggled && !state.context.isBiometricUnlockEnabled
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,70 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke.settings.resetInjiProps:invocation[0]": { type: "done.invoke.settings.resetInjiProps:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform.settings.resetInjiProps:invocation[0]": { type: "error.platform.settings.resetInjiProps:invocation[0]"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"resetInjiProps": "done.invoke.settings.resetInjiProps:invocation[0]";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"requestStoredContext": "xstate.init";
|
||||
"resetCredentialRegistryResponse": "CANCEL" | "UPDATE_HOST";
|
||||
"resetIsBiometricToggled": "DISMISS";
|
||||
"setBackupAndRestoreOptionExplored": "SET_IS_BACKUP_AND_RESTORE_EXPLORED";
|
||||
"setContext": "STORE_RESPONSE";
|
||||
"setIsBiometricToggled": "TOGGLE_BIOMETRIC_UNLOCK";
|
||||
"storeContext": "ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS" | "SET_IS_BACKUP_AND_RESTORE_EXPLORED" | "SHOWN_ACCOUNT_SELECTION_CONFIRMATION" | "STORE_RESPONSE" | "TOGGLE_BIOMETRIC_UNLOCK" | "UPDATE_HOST" | "UPDATE_NAME" | "UPDATE_VC_LABEL" | "done.invoke.settings.resetInjiProps:invocation[0]";
|
||||
"toggleBiometricUnlock": "TOGGLE_BIOMETRIC_UNLOCK";
|
||||
"updateCredentialRegistry": "done.invoke.settings.resetInjiProps:invocation[0]";
|
||||
"updateCredentialRegistryResponse": "error.platform.settings.resetInjiProps:invocation[0]";
|
||||
"updateCredentialRegistrySuccess": "done.invoke.settings.resetInjiProps:invocation[0]";
|
||||
"updateDefaults": "STORE_RESPONSE";
|
||||
"updateEsignetHostUrl": "UPDATE_HOST";
|
||||
"updateIsAccountSelectionConfirmationShown": "SHOWN_ACCOUNT_SELECTION_CONFIRMATION";
|
||||
"updateName": "UPDATE_NAME";
|
||||
"updatePartialDefaults": "STORE_RESPONSE";
|
||||
"updateUserShownWithHardwareKeystoreNotExists": "ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS";
|
||||
"updateVcLabel": "UPDATE_VC_LABEL";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"hasData": "STORE_RESPONSE";
|
||||
"hasPartialData": "STORE_RESPONSE";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"resetInjiProps": "UPDATE_HOST";
|
||||
};
|
||||
matchesStates: "idle" | "init" | "resetInjiProps" | "showInjiTourGuide" | "storingDefaults";
|
||||
tags: never;
|
||||
}
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.settings.resetInjiProps:invocation[0]': {
|
||||
type: 'done.invoke.settings.resetInjiProps:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.settings.resetInjiProps:invocation[0]': {
|
||||
type: 'error.platform.settings.resetInjiProps:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
resetInjiProps: 'done.invoke.settings.resetInjiProps:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
requestStoredContext: 'xstate.init';
|
||||
resetCredentialRegistryResponse: 'CANCEL' | 'UPDATE_HOST';
|
||||
resetIsBiometricToggled: 'DISMISS';
|
||||
setBackupAndRestoreOptionExplored: 'SET_IS_BACKUP_AND_RESTORE_EXPLORED';
|
||||
setContext: 'STORE_RESPONSE';
|
||||
setIsBiometricToggled: 'TOGGLE_BIOMETRIC_UNLOCK';
|
||||
storeContext:
|
||||
| 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS'
|
||||
| 'SET_IS_BACKUP_AND_RESTORE_EXPLORED'
|
||||
| 'SHOWN_ACCOUNT_SELECTION_CONFIRMATION'
|
||||
| 'STORE_RESPONSE'
|
||||
| 'TOGGLE_BIOMETRIC_UNLOCK'
|
||||
| 'UPDATE_HOST'
|
||||
| 'UPDATE_NAME'
|
||||
| 'UPDATE_VC_LABEL'
|
||||
| 'done.invoke.settings.resetInjiProps:invocation[0]';
|
||||
toggleBiometricUnlock: 'TOGGLE_BIOMETRIC_UNLOCK';
|
||||
updateCredentialRegistry: 'done.invoke.settings.resetInjiProps:invocation[0]';
|
||||
updateCredentialRegistryResponse: 'error.platform.settings.resetInjiProps:invocation[0]';
|
||||
updateCredentialRegistrySuccess: 'done.invoke.settings.resetInjiProps:invocation[0]';
|
||||
updateDefaults: 'STORE_RESPONSE';
|
||||
updateEsignetHostUrl: 'UPDATE_HOST';
|
||||
updateIsAccountSelectionConfirmationShown: 'SHOWN_ACCOUNT_SELECTION_CONFIRMATION';
|
||||
updateName: 'UPDATE_NAME';
|
||||
updatePartialDefaults: 'STORE_RESPONSE';
|
||||
updateUserShownWithHardwareKeystoreNotExists: 'ACCEPT_HARDWARE_SUPPORT_NOT_EXISTS';
|
||||
updateVcLabel: 'UPDATE_VC_LABEL';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
hasData: 'STORE_RESPONSE';
|
||||
hasPartialData: 'STORE_RESPONSE';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
resetInjiProps: 'UPDATE_HOST';
|
||||
};
|
||||
matchesStates:
|
||||
| 'idle'
|
||||
| 'init'
|
||||
| 'resetInjiProps'
|
||||
| 'showInjiTourGuide'
|
||||
| 'storingDefaults';
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ const model = createModel(
|
||||
requester,
|
||||
}),
|
||||
STORE_ERROR: (error: Error, requester?: string) => ({error, requester}),
|
||||
FETCH_ALL_WELLKNOWN_CONFIG: () => ({}),
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -233,6 +234,9 @@ export const storeMachine =
|
||||
CLEAR: {
|
||||
actions: 'forwardStoreRequest',
|
||||
},
|
||||
FETCH_ALL_WELLKNOWN_CONFIG: {
|
||||
actions: 'forwardStoreRequest',
|
||||
},
|
||||
STORE_RESPONSE: {
|
||||
actions: [
|
||||
send(
|
||||
@@ -442,6 +446,13 @@ export const storeMachine =
|
||||
await clear();
|
||||
break;
|
||||
}
|
||||
case 'FETCH_ALL_WELLKNOWN_CONFIG': {
|
||||
response = await fetchAllWellknownConfig(
|
||||
context.encryptionKey,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -586,6 +597,10 @@ export async function loadBackupData(data, encryptionKey) {
|
||||
await Storage.loadBackupData(data, encryptionKey);
|
||||
}
|
||||
|
||||
export async function fetchAllWellknownConfig(encryptionKey: string) {
|
||||
return await Storage.fetchAllWellknownConfig(encryptionKey);
|
||||
}
|
||||
|
||||
export async function getVCsData(key: string, encryptionKey: string) {
|
||||
try {
|
||||
let vcsData: Record<string, VC> = {};
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface Typegen0 {
|
||||
| 'APPEND'
|
||||
| 'CLEAR'
|
||||
| 'EXPORT'
|
||||
| 'FETCH_ALL_WELLKNOWN_CONFIG'
|
||||
| 'GET'
|
||||
| 'GET_VCS_DATA'
|
||||
| 'PREPEND'
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
import { useSelector } from '@xstate/react';
|
||||
import { useContext } from 'react';
|
||||
import {useSelector} from '@xstate/react';
|
||||
import {useContext} from 'react';
|
||||
import {
|
||||
ActivityLogEvents,
|
||||
selectActivities,
|
||||
selectIsRefreshing,
|
||||
selectWellknownIssuerMap,
|
||||
} from '../../machines/activityLog';
|
||||
import { GlobalContext } from '../../shared/GlobalContext';
|
||||
import {GlobalContext} from '../../shared/GlobalContext';
|
||||
|
||||
export function useHistoryTab() {
|
||||
const { appService } = useContext(GlobalContext);
|
||||
const activityLogService = appService.children.get('activityLog');
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const activityLogService = appService.children.get('activityLog')!!;
|
||||
const wellknownIssuerMap = useSelector(
|
||||
activityLogService,
|
||||
selectWellknownIssuerMap,
|
||||
);
|
||||
|
||||
return {
|
||||
activities: useSelector(activityLogService, selectActivities),
|
||||
|
||||
isRefreshing: useSelector(activityLogService, selectIsRefreshing),
|
||||
|
||||
getWellKnownIssuerMap: (issuerName: string) => {
|
||||
return wellknownIssuerMap[issuerName] ?? null;
|
||||
},
|
||||
|
||||
REFRESH: () => activityLogService.send(ActivityLogEvents.REFRESH()),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -134,9 +134,7 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = props => {
|
||||
<BannerNotification
|
||||
type={verificationStatus?.statusType as BannerStatus}
|
||||
message={t(`VcVerificationBanner:${verificationStatus?.statusType}`, {
|
||||
vcDetails: `${t(`VcDetails:${verificationStatus?.vcType}`)} ${
|
||||
verificationStatus?.vcNumber
|
||||
}`,
|
||||
vcDetails: `${verificationStatus.vcType} ${verificationStatus?.vcNumber}`,
|
||||
})}
|
||||
onClosePress={controller.RESET_VERIFICATION_STATUS}
|
||||
key={'reVerificationInProgress'}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const CredentialTypeSelectionScreen: React.FC<
|
||||
</Text>
|
||||
<View style={Theme.IssuersScreenStyles.issuersContainer}>
|
||||
<FlatList
|
||||
data={controller.credentialTypes}
|
||||
data={controller.supportedCredentialTypes}
|
||||
numColumns={1}
|
||||
keyExtractor={item => item.id}
|
||||
renderItem={({item}) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {useSelector} from '@xstate/react';
|
||||
import {
|
||||
selectCredentialTypes,
|
||||
selectSupportedCredentialTypes,
|
||||
selectErrorMessageType,
|
||||
selectIsBiometricCancelled,
|
||||
selectIsDone,
|
||||
@@ -41,7 +41,10 @@ export function useIssuerScreenController({route, navigation}) {
|
||||
service,
|
||||
selectSelectingCredentialType,
|
||||
),
|
||||
credentialTypes: useSelector(service, selectCredentialTypes),
|
||||
supportedCredentialTypes: useSelector(
|
||||
service,
|
||||
selectSupportedCredentialTypes,
|
||||
),
|
||||
verificationErrorMessage: useSelector(
|
||||
service,
|
||||
selectVerificationErrorMessage,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {Icon} from 'react-native-elements';
|
||||
import {View} from 'react-native';
|
||||
import {FaceVerificationAlertOverlay} from '../Scan/FaceVerificationAlertOverlay';
|
||||
import {SvgImage} from '../../components/ui/svg';
|
||||
import { LIVENESS_CHECK } from '../../shared/constants';
|
||||
import {LIVENESS_CHECK} from '../../shared/constants';
|
||||
|
||||
export const QrLogin: React.FC<QrLoginProps> = props => {
|
||||
const controller = useQrLogin(props);
|
||||
|
||||
@@ -15,7 +15,7 @@ import {SvgImage} from '../../components/ui/svg';
|
||||
import {View, I18nManager} from 'react-native';
|
||||
import {Text} from './../../components/ui';
|
||||
import {BannerStatusType} from '../../components/BannerNotification';
|
||||
import { LIVENESS_CHECK } from '../../shared/constants';
|
||||
import {LIVENESS_CHECK} from '../../shared/constants';
|
||||
|
||||
const ScanStack = createNativeStackNavigator();
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ import {
|
||||
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
|
||||
import {
|
||||
getVCsOrderedByPinStatus,
|
||||
isMosipVC,
|
||||
VCItemContainerFlowType,
|
||||
} from '../../shared/Utils';
|
||||
import {Issuers} from '../../shared/openId4VCI/Utils';
|
||||
import {FaceVerificationAlertOverlay} from './FaceVerificationAlertOverlay';
|
||||
import {Error} from '../../components/ui/Error';
|
||||
import {SvgImage} from '../../components/ui/svg';
|
||||
import { LIVENESS_CHECK } from '../../shared/constants';
|
||||
import {LIVENESS_CHECK} from '../../shared/constants';
|
||||
|
||||
export const SendVcScreen: React.FC = () => {
|
||||
const {t} = useTranslation('SendVcScreen');
|
||||
@@ -102,9 +102,7 @@ export const SendVcScreen: React.FC = () => {
|
||||
<Column
|
||||
style={Theme.SendVcScreenStyles.shareOptionButtonsContainer}
|
||||
backgroundColor={Theme.Colors.whiteBackgroundColor}>
|
||||
{[Issuers.MosipOtp, Issuers.Mosip].indexOf(
|
||||
controller.verifiableCredentialData.issuer,
|
||||
) !== -1 && (
|
||||
{isMosipVC(controller.verifiableCredentialData.issuer) && (
|
||||
<Button
|
||||
type="gradient"
|
||||
title={t('acceptRequestAndVerify')}
|
||||
|
||||
@@ -21,22 +21,21 @@ export const VerifyIdentityOverlay: React.FC<
|
||||
animationType: 'slide',
|
||||
arrowLeft: true,
|
||||
headerTitle: t('faceAuth'),
|
||||
presentationStyle: "overFullScreen",
|
||||
presentationStyle: 'overFullScreen',
|
||||
showClose: true,
|
||||
showHeader: true,
|
||||
};
|
||||
|
||||
|
||||
if (props.isLivenessEnabled) {
|
||||
modalProps.arrowLeft = false;
|
||||
modalProps.headerTitle = '';
|
||||
modalProps.showClose = false;
|
||||
modalProps.showHeader = false;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
{...modalProps}>
|
||||
<Modal {...modalProps}>
|
||||
<Column
|
||||
fill
|
||||
style={Theme.VerifyIdentityOverlayStyles.content}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {VCMetadata} from './VCMetadata';
|
||||
import {groupBy} from './javascript';
|
||||
import {Issuers} from './openId4VCI/Utils';
|
||||
|
||||
export const getVCsOrderedByPinStatus = (vcMetadatas: VCMetadata[]) => {
|
||||
const [pinned, unpinned] = groupBy(
|
||||
@@ -25,3 +26,7 @@ export interface CommunicationDetails {
|
||||
phoneNumber: string;
|
||||
emailId: string;
|
||||
}
|
||||
|
||||
export const isMosipVC = (issuer: string) => {
|
||||
return issuer === Issuers.Mosip || issuer === Issuers.MosipOtp;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {VC, VcIdType} from '../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import {Issuers, Protocols} from './openId4VCI/Utils';
|
||||
import {Protocols} from './openId4VCI/Utils';
|
||||
import {getMosipIdentifier} from './commonUtil';
|
||||
|
||||
const VC_KEY_PREFIX = 'VC';
|
||||
@@ -87,28 +87,18 @@ export function parseMetadatas(metadataStrings: object[]) {
|
||||
}
|
||||
|
||||
export const getVCMetadata = (context: object) => {
|
||||
const [issuer, protocol, requestId] =
|
||||
const [issuer, protocol, credentialId] =
|
||||
context.credentialWrapper?.identifier.split(':');
|
||||
// TODO(temp-solution): This is a temporary solution and will not work for every issuer
|
||||
// This should be re-written in a more standards compliant way later.
|
||||
if (issuer === Issuers.Sunbird) {
|
||||
return VCMetadata.fromVC({
|
||||
requestId: requestId ? requestId : null,
|
||||
issuer: issuer,
|
||||
protocol: protocol,
|
||||
id: context.verifiableCredential?.credential.credentialSubject
|
||||
.policyNumber,
|
||||
timestamp: context.timestamp ?? '',
|
||||
isVerified: context.vcMetadata.isVerified ?? false,
|
||||
});
|
||||
}
|
||||
|
||||
return VCMetadata.fromVC({
|
||||
requestId: requestId ? requestId : null,
|
||||
requestId: credentialId ?? null,
|
||||
issuer: issuer,
|
||||
protocol: protocol,
|
||||
id: getMosipIdentifier(
|
||||
context.verifiableCredential?.credential.credentialSubject,
|
||||
),
|
||||
id:
|
||||
context.verifiableCredential?.credential.credentialSubject.policyNumber ||
|
||||
getMosipIdentifier(
|
||||
context.verifiableCredential?.credential.credentialSubject,
|
||||
),
|
||||
timestamp: context.timestamp ?? '',
|
||||
isVerified: context.vcMetadata.isVerified ?? false,
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ export const API_URLS: ApiUrls = {
|
||||
buildURL: (issuerId: string): `/${string}` =>
|
||||
`/residentmobileapp/issuers/${issuerId}`,
|
||||
},
|
||||
// TODO: Remove unused api
|
||||
credentialTypes: {
|
||||
method: 'GET',
|
||||
buildURL: (issuerId: string): `/${string}` =>
|
||||
@@ -145,8 +146,13 @@ export const CACHED_API = {
|
||||
cacheKey: API_CACHED_STORAGE_KEYS.fetchIssuerConfig(issuerId),
|
||||
fetchCall: API.fetchIssuerConfig.bind(null, issuerId),
|
||||
}),
|
||||
fetchIssuerWellknownConfig: (issuerId: string, requestUrl: string) =>
|
||||
fetchIssuerWellknownConfig: (
|
||||
issuerId: string,
|
||||
requestUrl: string,
|
||||
isCachePreferred: boolean = false,
|
||||
) =>
|
||||
generateCacheAPIFunction({
|
||||
isCachePreferred,
|
||||
cacheKey: API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig(issuerId),
|
||||
fetchCall: API.fetchIssuerWellknownConfig.bind(null, requestUrl),
|
||||
}),
|
||||
|
||||
@@ -35,7 +35,7 @@ export const getRandomInt = (min, max) => {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
};
|
||||
export const generateBackupEncryptionKey = (
|
||||
password: string,
|
||||
salt: string,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import {Dimensions, Platform} from 'react-native';
|
||||
import {DEBUG_MODE, ESIGNET_HOST, MIMOTO_HOST, LIVENESS_DETECTION} from 'react-native-dotenv';
|
||||
import {
|
||||
DEBUG_MODE,
|
||||
ESIGNET_HOST,
|
||||
MIMOTO_HOST,
|
||||
LIVENESS_DETECTION,
|
||||
} from 'react-native-dotenv';
|
||||
import {Argon2iConfig} from './commonUtil';
|
||||
import {VcIdType} from '../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
|
||||
|
||||
@@ -15,10 +15,13 @@ import {
|
||||
import {
|
||||
BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS,
|
||||
DETAIL_VIEW_ADD_ON_FIELDS,
|
||||
getCredentialDefinition,
|
||||
getIdType,
|
||||
getCredentialTypes,
|
||||
} from '../../components/VC/common/VCUtils';
|
||||
import {getVerifiableCredential} from '../../machines/VerifiableCredential/VCItemMachine/VCItemSelectors';
|
||||
import {vcVerificationBannerDetails} from '../../components/BannerNotificationContainer';
|
||||
import {getErrorEventData, sendErrorEvent} from '../telemetry/TelemetryUtils';
|
||||
import {TelemetryConstants} from '../telemetry/TelemetryConstants';
|
||||
|
||||
export const Protocols = {
|
||||
OpenId4VCI: 'OpenId4VCI',
|
||||
@@ -31,44 +34,23 @@ export const Issuers = {
|
||||
Mosip: 'Mosip',
|
||||
};
|
||||
|
||||
/**
|
||||
* @param issuer of the VC as per the VC metadata in MMKV
|
||||
* @returns the ID-type to be used for further translation
|
||||
*
|
||||
* NOTE: This might be replaced by a more standards compliant way later.
|
||||
*/
|
||||
export function getIdType(issuer: string | undefined): string {
|
||||
if (issuer === Issuers.MosipOtp || issuer === Issuers.Mosip) {
|
||||
return 'nationalCard';
|
||||
}
|
||||
return 'insuranceCard';
|
||||
}
|
||||
|
||||
export function getVcVerificationDetails(
|
||||
statusType,
|
||||
vcMetadata,
|
||||
verifiableCredential,
|
||||
wellknown: Object,
|
||||
): vcVerificationBannerDetails {
|
||||
const idType = getIdType(
|
||||
wellknown,
|
||||
getCredentialTypes(getVerifiableCredential(verifiableCredential)),
|
||||
);
|
||||
return {
|
||||
statusType: statusType,
|
||||
vcType: getIDType(
|
||||
getVerifiableCredential(vcMetadata, verifiableCredential),
|
||||
),
|
||||
vcType: idType,
|
||||
vcNumber: vcMetadata.id,
|
||||
};
|
||||
}
|
||||
|
||||
export const ID_TYPE = {
|
||||
MOSIPVerifiableCredential: 'nationalCard',
|
||||
InsuranceCredential: 'insuranceCard',
|
||||
OpenG2PBeneficiaryVerifiableCredential: 'beneficiaryCard',
|
||||
OpenG2PRegistryVerifiableCredential: 'socialRegistryCard',
|
||||
};
|
||||
|
||||
export const getIDType = (verifiableCredential: VerifiableCredential) => {
|
||||
return ID_TYPE[verifiableCredential.type[1]];
|
||||
};
|
||||
|
||||
export const ACTIVATION_NEEDED = [Issuers.Mosip, Issuers.MosipOtp];
|
||||
|
||||
export const isActivationNeeded = (issuer: string) => {
|
||||
@@ -77,7 +59,7 @@ export const isActivationNeeded = (issuer: string) => {
|
||||
|
||||
export const Issuers_Key_Ref = 'OpenId4VCI_KeyPair';
|
||||
|
||||
export const getIdentifier = (context, credential) => {
|
||||
export const getIdentifier = (context, credential: VerifiableCredential) => {
|
||||
const credentialIdentifier = credential.credential.id;
|
||||
const credId = credentialIdentifier.startsWith('did')
|
||||
? credentialIdentifier.split(':')
|
||||
@@ -108,35 +90,23 @@ export const getCredentialRequestBody = async (
|
||||
};
|
||||
};
|
||||
|
||||
export const getCredentialType = (context: any) => {
|
||||
return context.selectedCredentialType?.credential_definition?.type
|
||||
? context.selectedCredentialType.credential_definition.type
|
||||
: context.selectedIssuer?.credential_type
|
||||
? context.selectedIssuer.credential_type
|
||||
: ['VerifiableCredential', 'MOSIPVerifiableCredential'];
|
||||
};
|
||||
|
||||
export const updateCredentialInformation = (context, credential) => {
|
||||
let credentialWrapper: CredentialWrapper = {};
|
||||
credentialWrapper.verifiableCredential = credential;
|
||||
credentialWrapper.identifier = getIdentifier(context, credential);
|
||||
credentialWrapper.generatedOn = new Date();
|
||||
credentialWrapper.verifiableCredential.wellKnown =
|
||||
context.selectedIssuer['.well-known'];
|
||||
credentialWrapper.verifiableCredential.credentialTypes =
|
||||
context.selectedIssuer['credential_type'];
|
||||
credentialWrapper.verifiableCredential.issuerLogo =
|
||||
getDisplayObjectForCurrentLanguage(context.selectedIssuer.display)?.logo;
|
||||
credentialWrapper.vcMetadata = context.vcMetadata || {};
|
||||
return credentialWrapper;
|
||||
};
|
||||
|
||||
export const updateVCmetadataOfCredentialWrapper = (
|
||||
export const updateCredentialInformation = (
|
||||
context,
|
||||
credentialWrapper: CredentialWrapper,
|
||||
) => {
|
||||
credentialWrapper.vcMetadata = context.vcMetadata;
|
||||
return credentialWrapper;
|
||||
credential: VerifiableCredential,
|
||||
): CredentialWrapper => {
|
||||
return {
|
||||
verifiableCredential: {
|
||||
...credential,
|
||||
wellKnown: context.selectedIssuer['.well-known'],
|
||||
credentialTypes: credential.credential.type ?? ['VerifiableCredential'],
|
||||
issuerLogo: getDisplayObjectForCurrentLanguage(
|
||||
context.selectedIssuer.display,
|
||||
)?.logo,
|
||||
},
|
||||
identifier: getIdentifier(context, credential),
|
||||
generatedOn: new Date(),
|
||||
vcMetadata: context.vcMetadata || {},
|
||||
};
|
||||
};
|
||||
|
||||
export const getDisplayObjectForCurrentLanguage = (
|
||||
@@ -157,11 +127,12 @@ export const getDisplayObjectForCurrentLanguage = (
|
||||
|
||||
export const constructAuthorizationConfiguration = (
|
||||
selectedIssuer: issuerType,
|
||||
supportedScopes: string,
|
||||
supportedScope: string,
|
||||
) => {
|
||||
return {
|
||||
issuer: selectedIssuer.credential_issuer,
|
||||
clientId: selectedIssuer.client_id,
|
||||
scopes: supportedScopes,
|
||||
scopes: [supportedScope],
|
||||
additionalHeaders: selectedIssuer.additional_headers,
|
||||
redirectUrl: selectedIssuer.redirect_uri,
|
||||
additionalParameters: {ui_locales: i18n.language},
|
||||
@@ -197,37 +168,62 @@ export const getJWK = async publicKey => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getSelectedCredentialTypeDetails = (
|
||||
wellknown: any,
|
||||
vcCredentialTypes: Object[],
|
||||
): Object => {
|
||||
for (let credential in wellknown.credentials_supported) {
|
||||
const credentialDetails = wellknown.credentials_supported[credential];
|
||||
|
||||
if (
|
||||
JSON.stringify(credentialDetails.credential_definition.type) ===
|
||||
JSON.stringify(vcCredentialTypes)
|
||||
) {
|
||||
return credentialDetails;
|
||||
}
|
||||
}
|
||||
console.error(
|
||||
'Selected credential type is not available in wellknown config supported credentials list',
|
||||
);
|
||||
sendErrorEvent(
|
||||
getErrorEventData(
|
||||
TelemetryConstants.FlowType.wellknownConfig,
|
||||
TelemetryConstants.ErrorId.mismatch,
|
||||
TelemetryConstants.ErrorMessage.wellknownConfigMismatch,
|
||||
),
|
||||
);
|
||||
return {};
|
||||
};
|
||||
|
||||
export const getCredentialIssuersWellKnownConfig = async (
|
||||
issuer: string,
|
||||
wellknown: string,
|
||||
vcCredentialTypes: Object[],
|
||||
defaultFields: string[],
|
||||
) => {
|
||||
let fields: string[] = [];
|
||||
let response = null;
|
||||
if (issuer === Issuers.MosipOtp) {
|
||||
fields = defaultFields;
|
||||
} else if (wellknown) {
|
||||
response = await CACHED_API.fetchIssuerWellknownConfig(issuer, wellknown);
|
||||
let fields: string[] = defaultFields;
|
||||
let credentialDetails: any;
|
||||
if (wellknown) {
|
||||
const response = await CACHED_API.fetchIssuerWellknownConfig(
|
||||
issuer,
|
||||
wellknown,
|
||||
);
|
||||
if (response) {
|
||||
if (
|
||||
Array.isArray(response.credentials_supported) &&
|
||||
response?.credentials_supported[0].order
|
||||
) {
|
||||
fields = response?.credentials_supported[0].order;
|
||||
credentialDetails = getSelectedCredentialTypeDetails(
|
||||
response,
|
||||
vcCredentialTypes,
|
||||
);
|
||||
if (Object.keys(credentialDetails).includes('order')) {
|
||||
fields = credentialDetails.order;
|
||||
} else {
|
||||
const credentialDefinition = getCredentialDefinition(
|
||||
response,
|
||||
vcCredentialTypes,
|
||||
fields = Object.keys(
|
||||
credentialDetails.credential_definition.credentialSubject,
|
||||
);
|
||||
fields = credentialDefinition
|
||||
? Object.keys(credentialDefinition.credentialSubject)
|
||||
: [];
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
wellknown: response,
|
||||
wellknown: credentialDetails,
|
||||
fields: fields,
|
||||
};
|
||||
};
|
||||
@@ -235,13 +231,13 @@ export const getCredentialIssuersWellKnownConfig = async (
|
||||
export const getDetailedViewFields = async (
|
||||
issuer: string,
|
||||
wellknown: string,
|
||||
credentialTypes: Object[],
|
||||
vcCredentialTypes: Object[],
|
||||
defaultFields: string[],
|
||||
) => {
|
||||
let response = await getCredentialIssuersWellKnownConfig(
|
||||
issuer,
|
||||
wellknown,
|
||||
credentialTypes,
|
||||
vcCredentialTypes,
|
||||
defaultFields,
|
||||
);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
MY_VCS_STORE_KEY,
|
||||
SETTINGS_STORE_KEY,
|
||||
ENOENT,
|
||||
API_CACHED_STORAGE_KEYS,
|
||||
} from './constants';
|
||||
import FileStorage, {
|
||||
getFilePath,
|
||||
@@ -147,9 +148,30 @@ class Storage {
|
||||
return true;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error while loading backup data ', error);
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
static fetchAllWellknownConfig = async (encryptionKey: string) => {
|
||||
let wellknownConfigData: Record<string, Object> = {};
|
||||
const allKeysInDB = await MMKV.indexer.strings.getKeys();
|
||||
const wellknownConfigCacheKey =
|
||||
API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig('');
|
||||
const wellknownKeys = allKeysInDB.filter(key =>
|
||||
key.includes(wellknownConfigCacheKey),
|
||||
);
|
||||
|
||||
for (const wellknownKey of wellknownKeys) {
|
||||
const configData = await this.getItem(wellknownKey, encryptionKey);
|
||||
const decryptedConfigData = await decryptJson(encryptionKey, configData);
|
||||
wellknownConfigData[
|
||||
wellknownKey.substring(wellknownConfigCacheKey.length)
|
||||
] = JSON.parse(JSON.stringify(decryptedConfigData));
|
||||
}
|
||||
return wellknownConfigData;
|
||||
};
|
||||
|
||||
static isVCStorageInitialised = async (): Promise<boolean> => {
|
||||
try {
|
||||
const res = await FileStorage.getInfo(vcDirectoryPath);
|
||||
@@ -315,7 +337,6 @@ class Storage {
|
||||
encryptionKey,
|
||||
JSON.stringify(vc),
|
||||
);
|
||||
const tmp = VCMetadata.fromVC(key);
|
||||
// Save the VC to disk
|
||||
await this.setItem(updatedVcKey, encryptedVC, encryptionKey);
|
||||
});
|
||||
|
||||
@@ -19,6 +19,7 @@ export const TelemetryConstants = {
|
||||
remove: 'remove VC',
|
||||
removeVcMetadata: 'VC metadata removed',
|
||||
vcVerification: 'VC Verification',
|
||||
wellknownConfig: 'Wellknown config',
|
||||
}),
|
||||
|
||||
EndEventStatus: Object.freeze({
|
||||
@@ -45,6 +46,8 @@ export const TelemetryConstants = {
|
||||
'Tampered cards detected and removed for security reasons. Please download again',
|
||||
privateKeyUpdationFailed: 'Failed to store private key in keystore',
|
||||
vcVerificationFailed: 'VC verification Failed with Range Error - ',
|
||||
wellknownConfigMismatch:
|
||||
'Selected credential type is not available in wellknown config supported credentials list',
|
||||
}),
|
||||
|
||||
ErrorId: Object.freeze({
|
||||
|
||||
Reference in New Issue
Block a user