Inji-411: vc load optimisation (#927)

* feat(inji-406): store vc before storing hmac to avoid race condition

Signed-off-by: Tilak Puli <tilakpuli15@gmail.com>

* feat(inji-406): waiting until vc saved completely before displaying VC card

Signed-off-by: Tilak Puli <tilakpuli15@gmail.com>

* feat(inji-411): read and cache vc files data on welcome screen

Signed-off-by: Tilak Puli <tilakpuli15@gmail.com>

* feat(inji-411): remove formatting for unnecessary files

Signed-off-by: Tilak Puli <tilakpuli15@gmail.com>

---------

Signed-off-by: Tilak Puli <tilakpuli15@gmail.com>
This commit is contained in:
Tilak Puli
2023-10-16 17:34:22 +05:30
committed by GitHub
parent 853cda3625
commit 54a9a930c2
5 changed files with 144 additions and 55 deletions

View File

@@ -0,0 +1,29 @@
fileignoreconfig:
- filename: package.json
checksum: 30e3a548809705ba38385a1c286b312629ac5dd7dea0d6e26ffb9daf8def312d
- filename: package-lock.json
checksum: 4d595248dfa13967eef07ffee65f86809672a0d145d74b9df55b296bdbe29f78
- filename: components/PasscodeVerify.tsx
checksum: 14654c0f038979fcd0d260170a45894a072f81e0767ca9a0e66935d33b5cc703
- filename: i18n.ts
checksum: 75dd5536038ba198aa7b12eb6d2c2e7042c9ce292e5a0d5c90883ae5b2312b1e
- filename: screens/BiometricScreenController.ts
checksum: b3d0184fb894f4a9ffa1a4d277d2975495dbc47771593895bf1999deabafeb94
- filename: screens/Home/MyVcs/IdInputModal.tsx
checksum: ec48ebeaf46b8fbc756f19ef8ffe8901ce0528aef164f3c7ffdeec36fb53ffc6
- filename: components/Passcode.tsx
checksum: db4a18001be8c63bf7ffb389359861401fa1d22261b10ad729a76fd431c019a7
- filename: screens/PasscodeScreen.tsx
checksum: 0cc5b91350e491a058ee8a1878a496c16b65f14969e989bdb1c354f6e9b8c03c
- filename: locales/spa.json
checksum: 981103ff872d6f54610468c7ead65873d9294a11092649b105c552f770f0214b
- filename: screens/AuthScreen.tsx
checksum: 2c1183b2ad8ec27adf8f389a2511805493f229fdda674064e2579d2032119d1c
- filename: screens/BiometricScreen.tsx
checksum: 7a730731aaa7540eec9d05d73de277a665dc06425666280842e0f9ba6e5b8514
- filename: screens/AuthScreenController.ts
checksum: 18af825821bc95e1056050623b804a5a8e7435b9e3383916a5d63024eeba9553
- filename: screens/WelcomeScreenController.ts
checksum: d8fe74404c80bf435459f4d20427a661fb622f0ee9f754345616abd346b98d14
- filename: shared/telemetry/TelemetryUtils.js
checksum: 9a61cd59a3718adf1f14faf3024fec66a3295ef373878a878a28e5cb1287afaa

View File

@@ -25,6 +25,7 @@ import {
isCustomSecureKeystore,
} from '../shared/cryptoutil/cryptoUtil';
import {VCMetadata} from '../shared/VCMetadata';
import FileStorage, {getFilePath} from '../shared/fileStorage';
export const keyinvalidatedString =
'Key Invalidated due to biometric enrollment';
@@ -173,7 +174,7 @@ export const storeMachine =
},
},
ready: {
entry: 'notifyParent',
entry: ['notifyParent', 'cacheVCFilesData'],
invoke: {
src: 'store',
id: '_store',
@@ -259,6 +260,18 @@ export const storeMachine =
setEncryptionKey: model.assign({
encryptionKey: (_, event) => event.key,
}),
cacheVCFilesData: context => {
getItem(MY_VCS_STORE_KEY, [], context.encryptionKey).then(vcList => {
if (vcList) {
vcList?.forEach((vcMetadataStr: string) => {
const vcKey =
VCMetadata.fromVcMetadataString(vcMetadataStr).getVcKey();
FileStorage.readAndCacheFile(getFilePath(vcKey));
});
}
});
},
},
services: {
@@ -289,6 +302,7 @@ export const storeMachine =
);
}
},
checkStorageInitialisedOrNot: () => async callback => {
const isDirectoryExist = await Storage.isVCStorageInitialised();
if (!isDirectoryExist) {

4
package-lock.json generated
View File

@@ -84,7 +84,7 @@
"react-native-vector-icons": "^10.0.0",
"short-unique-id": "^4.4.4",
"simple-pem2jwk": "^0.2.4",
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
"telemetry-sdk": "git://github.com/mosip/sunbird-telemetry-sdk.git#develop",
"xstate": "^4.35.0"
},
"devDependencies": {
@@ -53475,7 +53475,7 @@
"telemetry-sdk": {
"version": "git+ssh://git@github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
"integrity": "sha512-aeA7uO77JzNQVSuUpxzUXK3I+BtYiOzDhcmYbD6R3pAETun4toP1/GR5PBfT9/iE3N5MdGJg70sQArwCIL1XaQ==",
"from": "telemetry-sdk@git://github.com/mosip/sunbird-telemetry-sdk.git#f762be5732ee552c0c70bdd540aa4e2701554c71",
"from": "telemetry-sdk@git://github.com/mosip/sunbird-telemetry-sdk.git#develop",
"requires": {
"axios": "^1.4.0",
"grunt-karma": "^0.12.2",

87
shared/fileStorage.ts Normal file
View File

@@ -0,0 +1,87 @@
import {
DocumentDirectoryPath,
exists,
mkdir,
readFile,
stat,
unlink,
writeFile,
} from 'react-native-fs';
interface CacheData {
data?: any;
count?: number;
}
interface Cache {
[key: string]: CacheData;
}
class FileStorage {
cache: Cache = {};
async readFile(path: string) {
return await readFile(path, 'utf8');
}
async readFromCacheFile(path: string) {
if (this.cache[path]?.data) {
const count = this.cache[path]?.count ?? 0;
const data = this.cache[path]?.data;
if (count != undefined && count <= 1) {
this.cache[path] = {};
} else {
this.cache[path].count = count - 1;
}
return data;
}
return this.readFile(path);
}
async readAndCacheFile(path: string, useCount: number = 1) {
const data = await this.readFile(path);
this.cache[path] = {
data,
count: useCount,
};
return data;
}
async writeFile(path: string, data: string) {
return await writeFile(path, data, 'utf8');
}
async createDirectory(path: string) {
return await mkdir(path);
}
async exists(path: string) {
return await exists(path);
}
async removeItem(path: string) {
return await unlink(path);
}
async getInfo(path: string) {
return await stat(path);
}
}
export default new FileStorage();
/**
* iOS: /var/mobile/Containers/Data/Application/196A05AD-6B11-403D-BA2D-6DC1F30075E1/Documents/inji/VC/<filename>
* android: /data/user/0/io.mosip.residentapp/files/inji/VC/<filename>
* These paths are coming from DocumentDirectoryPath in react-native-fs.
*/
export const getFilePath = (key: string) => {
return `${vcDirectoryPath}/${key}.txt`;
};
export const vcDirectoryPath = `${DocumentDirectoryPath}/inji/VC`;

View File

@@ -1,14 +1,5 @@
import {MMKVLoader} from 'react-native-mmkv-storage';
import CryptoJS from 'crypto-js';
import {
DocumentDirectoryPath,
exists,
mkdir,
readFile,
stat,
unlink,
writeFile,
} from 'react-native-fs';
import getAllConfigurations from './commonprops/commonProps';
import {Platform} from 'react-native';
import {
@@ -25,9 +16,9 @@ import {
import {VCMetadata} from './VCMetadata';
import {ENOENT, getItem} from '../machines/store';
import {MY_VCS_STORE_KEY, RECEIVED_VCS_STORE_KEY} from './constants';
import FileStorage, {getFilePath, vcDirectoryPath} from './fileStorage';
export const MMKV = new MMKVLoader().initialize();
const vcDirectoryPath = `${DocumentDirectoryPath}/inji/VC`;
export const API_CACHED_STORAGE_KEYS = {
fetchIssuers: 'CACHE_FETCH_ISSUERS',
@@ -48,7 +39,7 @@ async function generateHmac(
class Storage {
static isVCStorageInitialised = async (): Promise<boolean> => {
try {
const res = await stat(vcDirectoryPath);
const res = await FileStorage.getInfo(vcDirectoryPath);
return res.isDirectory();
} catch (_) {
return false;
@@ -148,7 +139,7 @@ class Storage {
}
private static async readHmacForVC(key: string, encryptionKey: string) {
const encryptedHMACofCurrentVC = await MMKV.getItem(getVCKeyName(key));
const encryptedHMACofCurrentVC = await MMKV.getItem(key);
if (encryptedHMACofCurrentVC) {
return decryptJson(encryptionKey, encryptedHMACofCurrentVC);
}
@@ -156,14 +147,13 @@ class Storage {
}
private static async readVCFromFile(key: string) {
const path = getFilePath(key);
return await readFile(path, 'utf8');
return await FileStorage.readFromCacheFile(getFilePath(key));
}
private static async storeVC(key: string, data: string) {
await mkdir(vcDirectoryPath);
await FileStorage.createDirectory(vcDirectoryPath);
const path = getFilePath(key);
return await writeFile(path, data, 'utf8');
return await FileStorage.writeFile(path, data);
}
private static async storeVcHmac(
@@ -174,15 +164,15 @@ class Storage {
const HMACofVC = await generateHmac(encryptionKey, data);
console.log('[Inji-406]: Updating hmac of the vc: ', HMACofVC);
const encryptedHMACofVC = await encryptJson(encryptionKey, HMACofVC);
await MMKV.setItem(getVCKeyName(key), encryptedHMACofVC);
await MMKV.setItem(key, encryptedHMACofVC);
}
static removeItem = async (key: string) => {
if (VCMetadata.isVCKey(key)) {
const path = getFilePath(key);
const isFileExists = await exists(path);
const isFileExists = await FileStorage.exists(path);
if (isFileExists) {
return await unlink(path);
return await FileStorage.removeItem(path);
} else {
console.log('file not exist`s');
}
@@ -192,8 +182,8 @@ class Storage {
static clear = async () => {
try {
(await exists(`${vcDirectoryPath}`)) &&
(await unlink(`${vcDirectoryPath}`));
(await FileStorage.exists(`${vcDirectoryPath}`)) &&
(await FileStorage.removeItem(`${vcDirectoryPath}`));
MMKV.clearStore();
} catch (e) {
console.log('Error Occurred while Clearing Storage.', e);
@@ -218,35 +208,4 @@ class Storage {
};
}
/**
* The VC file name will not have the pinned / unpinned state, we will splice the state as this will change.
* replace ':' with '_' in the key to get the file name as ':' are not allowed in filenames
* eg: "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628" is changed to "vc_UIN_6732935275_e7426576-112f-466a-961a-1ed9635db628"
*/
const getFileName = (key: string) => {
return key.split(':').splice(0, 4).join('_');
};
/**
* iOS: /var/mobile/Containers/Data/Application/196A05AD-6B11-403D-BA2D-6DC1F30075E1/Documents/inji/VC/<filename>
* android: /data/user/0/io.mosip.residentapp/files/inji/VC/<filename>
* These paths are coming from DocumentDirectoryPath in react-native-fs.
*/
const getFilePath = (key: string) => {
return `${vcDirectoryPath}/${key}.txt`;
};
/**
* The VC key will not have the pinned / unpinned state, we will splice the state as this will change.
* eg: "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628:true" is changed to "vc:UIN:6732935275:e7426576-112f-466a-961a-1ed9635db628"
*/
const getVCKeyName = (key: string) => {
return key;
};
// To print the MMKV data cal this function in getItem
const getMMKVData = async () => {
return await MMKV.indexer.getKeys();
};
export default Storage;