mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
SEL-566: Navigate Home based on document validity (#768)
* feat: navigate home if atleast one valid document is present * update comments * Review: Remove unnecessary continue statement * feat: add tracking
This commit is contained in:
@@ -42,6 +42,7 @@ import {
|
||||
import {
|
||||
checkIfPassportDscIsInTree,
|
||||
checkPassportSupported,
|
||||
hasAnyValidRegisteredDocument,
|
||||
isDocumentNullified,
|
||||
isUserRegistered,
|
||||
isUserRegisteredWithAlternativeCSCA,
|
||||
@@ -186,6 +187,7 @@ interface ProvingState {
|
||||
_closeConnections: () => void;
|
||||
_generatePayload: () => Promise<any>;
|
||||
_handleWebSocketMessage: (event: MessageEvent) => Promise<void>;
|
||||
_handleRegisterErrorOrFailure: () => void;
|
||||
_startSocketIOStatusListener: (
|
||||
receivedUuid: string,
|
||||
endpointType: EndpointType,
|
||||
@@ -228,7 +230,7 @@ export const useProvingStore = create<ProvingState>((set, get) => {
|
||||
) {
|
||||
setTimeout(() => {
|
||||
if (navigationRef.isReady()) {
|
||||
navigationRef.navigate('Launch');
|
||||
get()._handleRegisterErrorOrFailure();
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
@@ -395,6 +397,23 @@ export const useProvingStore = create<ProvingState>((set, get) => {
|
||||
}
|
||||
},
|
||||
|
||||
_handleRegisterErrorOrFailure: async () => {
|
||||
try {
|
||||
const hasValid = await hasAnyValidRegisteredDocument();
|
||||
if (navigationRef.isReady()) {
|
||||
if (hasValid) {
|
||||
navigationRef.navigate('Home');
|
||||
} else {
|
||||
navigationRef.navigate('Launch');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (navigationRef.isReady()) {
|
||||
navigationRef.navigate('Launch');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_startSocketIOStatusListener: (
|
||||
receivedUuid: string,
|
||||
endpointType: EndpointType,
|
||||
|
||||
@@ -18,7 +18,18 @@ import {
|
||||
import { DocumentCategory } from '@selfxyz/common';
|
||||
import { poseidon2, poseidon5 } from 'poseidon-lite';
|
||||
|
||||
import { DocumentEvents } from '../../consts/analytics';
|
||||
import {
|
||||
getAllDocuments,
|
||||
loadPassportDataAndSecret,
|
||||
loadSelectedDocument,
|
||||
setSelectedDocument,
|
||||
storePassportData,
|
||||
} from '../../providers/passportDataProvider';
|
||||
import { useProtocolStore } from '../../stores/protocolStore';
|
||||
import analytics from '../../utils/analytics';
|
||||
|
||||
const { trackEvent } = analytics();
|
||||
|
||||
export type PassportSupportStatus =
|
||||
| 'passport_metadata_missing'
|
||||
@@ -250,3 +261,128 @@ function formatCSCAPem(cscaPem: string): string {
|
||||
}
|
||||
return cleanedPem;
|
||||
}
|
||||
|
||||
export function isPassportDataValid(passportData: PassportData) {
|
||||
if (!passportData) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
error: 'Passport data is null',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!passportData.passportMetadata) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
error: 'Passport metadata is null',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!passportData.passportMetadata.dg1HashFunction) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
mock: passportData.mock,
|
||||
dsc: passportData.dsc,
|
||||
error: 'DG1 hash function is null',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!passportData.passportMetadata.eContentHashFunction) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
mock: passportData.mock,
|
||||
dsc: passportData.dsc,
|
||||
documentCategory: passportData.documentCategory,
|
||||
error: 'EContent hash function is null',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!passportData.passportMetadata.signedAttrHashFunction) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
mock: passportData.mock,
|
||||
dsc: passportData.dsc,
|
||||
documentCategory: passportData.documentCategory,
|
||||
error: 'Signed attribute hash function is null',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function migratePassportData(passportData: PassportData): PassportData {
|
||||
const migratedData = { ...passportData } as any;
|
||||
if (!('documentCategory' in migratedData) || !('mock' in migratedData)) {
|
||||
if ('documentType' in migratedData && migratedData.documentType) {
|
||||
migratedData.mock = migratedData.documentType.startsWith('mock');
|
||||
migratedData.documentCategory = migratedData.documentType.includes(
|
||||
'passport',
|
||||
)
|
||||
? 'passport'
|
||||
: 'id_card';
|
||||
} else {
|
||||
migratedData.documentType = 'passport';
|
||||
migratedData.documentCategory = 'passport';
|
||||
migratedData.mock = false;
|
||||
}
|
||||
// console.log('Migrated passport data:', migratedData);
|
||||
}
|
||||
return migratedData as PassportData;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function sequentially checks all documents for a valid registered document.
|
||||
* Since it uses fetch_all and loadSelectedDocument, it cannot be parallelised.
|
||||
*/
|
||||
export async function hasAnyValidRegisteredDocument(): Promise<boolean> {
|
||||
const allDocuments = await getAllDocuments();
|
||||
for (const documentId of Object.keys(allDocuments)) {
|
||||
try {
|
||||
await setSelectedDocument(documentId);
|
||||
const selectedDocument = await loadSelectedDocument();
|
||||
if (!selectedDocument) continue;
|
||||
let { data: passportData } = selectedDocument;
|
||||
if (!isPassportDataValid(passportData)) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
error: 'Passport data is not valid',
|
||||
documentId,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const migratedPassportData = migratePassportData(passportData);
|
||||
if (migratedPassportData !== passportData) {
|
||||
await storePassportData(migratedPassportData);
|
||||
passportData = migratedPassportData;
|
||||
}
|
||||
const environment = migratedPassportData.mock ? 'stg' : 'prod';
|
||||
const documentCategory = migratedPassportData.documentCategory;
|
||||
const authorityKeyIdentifier =
|
||||
migratedPassportData.dsc_parsed?.authorityKeyIdentifier;
|
||||
if (!authorityKeyIdentifier) {
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
error: 'Authority key identifier is null',
|
||||
documentId,
|
||||
documentCategory,
|
||||
mock: migratedPassportData.mock,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
await useProtocolStore
|
||||
.getState()
|
||||
[documentCategory].fetch_all(environment, authorityKeyIdentifier);
|
||||
const passportDataAndSecret = await loadPassportDataAndSecret();
|
||||
if (!passportDataAndSecret) continue;
|
||||
const { secret } = JSON.parse(passportDataAndSecret);
|
||||
const isRegistered = await isUserRegistered(migratedPassportData, secret);
|
||||
if (isRegistered) {
|
||||
trackEvent(DocumentEvents.DOCUMENT_VALIDATED, {
|
||||
documentId,
|
||||
documentCategory,
|
||||
mock: migratedPassportData.mock,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error in hasAnyValidRegisteredDocument: ${error}`);
|
||||
trackEvent(DocumentEvents.VALIDATE_DOCUMENT_FAILED, {
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
documentId,
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user