Skip to content

Commit

Permalink
added support for remote proof bundles
Browse files Browse the repository at this point in the history
Signed-off-by: wadeking98 <[email protected]>
  • Loading branch information
wadeking98 committed Nov 8, 2023
1 parent 374b616 commit 942b833
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 22 deletions.
1 change: 1 addition & 0 deletions packages/legacy/core/App/contexts/configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface ConfigurationContext {
credentialEmptyList: React.FC<EmptyListProps>
developer: React.FC
OCABundleResolver: OCABundleResolverType
proofTemplateBaseUrl?: string
scan: React.FC<ScanProps>
useBiometry: React.FC
record: React.FC<RecordProps>
Expand Down
165 changes: 157 additions & 8 deletions packages/legacy/core/App/hooks/proof-request-templates.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,167 @@
import { ProofRequestTemplate } from '../../verifier'
import axios from 'axios'
import { useEffect, useState } from 'react'

import { AnonCredsProofRequestTemplatePayload, ProofRequestTemplate, useProofRequestTemplates } from '../../verifier'
import { useConfiguration } from '../contexts/configuration'
import { useStore } from '../contexts/store'

export interface ProofBundleResolverType {
resolve: (acceptDevRestrictions: boolean) => Promise<ProofRequestTemplate[] | undefined>
resolveById: (templateId: string, acceptDevRestrictions: boolean) => Promise<ProofRequestTemplate | undefined>
}

const useRemoteProofBundleResolver = (indexFileBaseUrl: string | undefined): ProofBundleResolverType => {
if (indexFileBaseUrl) {
return new RemoteProofBundleResolver(indexFileBaseUrl)

Check warning on line 15 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L15

Added line #L15 was not covered by tests
} else {
return new DefaultProofBundleResolver()
}
}

const calculatePreviousYear = (yearOffset: number) => {
const pastDate = new Date()
pastDate.setFullYear(pastDate.getFullYear() + yearOffset)
return parseInt(pastDate.toISOString().split('T')[0].replace(/-/g, ''))

Check warning on line 24 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L22-L24

Added lines #L22 - L24 were not covered by tests
}

const applyTemplateMarkers = (templates: any): any => {
if (!templates) return templates
const markerActions: { [key: string]: (param: string) => string } = {
now: () => Math.floor(new Date().getTime() / 1000).toString(),
currentDate: (offset: string) => calculatePreviousYear(parseInt(offset)).toString(),

Check warning on line 31 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L30-L31

Added lines #L30 - L31 were not covered by tests
}
let templateString = JSON.stringify(templates)
const markers = [...templateString.matchAll(/"@\{(\w+)(?:\((\S*)\))?\}"/gm)]

markers.forEach((marker) => {
const markerValue = markerActions[marker[1] as string](marker[2])
templateString = templateString.replace(marker[0], markerValue)

Check warning on line 38 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L37-L38

Added lines #L37 - L38 were not covered by tests
})
return JSON.parse(templateString)
}

const applyDevRestrictions = (templates: ProofRequestTemplate[]): ProofRequestTemplate[] => {
return templates.map((temp) => {
return {

Check warning on line 45 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L44-L45

Added lines #L44 - L45 were not covered by tests
...temp,
payload: {
...temp.payload,
data: (temp.payload as AnonCredsProofRequestTemplatePayload).data.map((data) => {
return {

Check warning on line 50 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L49-L50

Added lines #L49 - L50 were not covered by tests
...data,
requestedAttributes: data.requestedAttributes?.map((attr) => {
return {

Check warning on line 53 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L52-L53

Added lines #L52 - L53 were not covered by tests
...attr,
restrictions: [...(attr.restrictions ?? []), ...(attr.devRestrictions ?? [])],
devRestrictions: [],
}
}),
requestedPredicates: data.requestedPredicates?.map((pred) => {
return {

Check warning on line 60 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L59-L60

Added lines #L59 - L60 were not covered by tests
...pred,
restrictions: [...(pred.restrictions ?? []), ...(pred.devRestrictions ?? [])],
devRestrictions: [],
}
}),
}
}),
},
}
})
}

export class RemoteProofBundleResolver implements ProofBundleResolverType {
private remoteServer
private templateData: ProofRequestTemplate[] | undefined

public constructor(indexFileBaseUrl: string) {
this.remoteServer = axios.create({

Check warning on line 78 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L77-L78

Added lines #L77 - L78 were not covered by tests
baseURL: indexFileBaseUrl,
})
}
public async resolve(acceptDevRestrictions: boolean): Promise<ProofRequestTemplate[] | undefined> {

Check warning on line 82 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L82

Added line #L82 was not covered by tests
if (this.templateData) {
let templateData = this.templateData

Check warning on line 84 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L84

Added line #L84 was not covered by tests
if (acceptDevRestrictions) {
templateData = applyDevRestrictions(templateData)

Check warning on line 86 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L86

Added line #L86 was not covered by tests
}
return Promise.resolve(templateData)

Check warning on line 88 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L88

Added line #L88 was not covered by tests
}
return this.remoteServer.get('proof-templates.json').then((response) => {
try {
let templateData: ProofRequestTemplate[] = response.data
this.templateData = templateData

Check warning on line 93 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L90-L93

Added lines #L90 - L93 were not covered by tests
if (acceptDevRestrictions) {
templateData = applyDevRestrictions(templateData)

Check warning on line 95 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L95

Added line #L95 was not covered by tests
}
return templateData

Check warning on line 97 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L97

Added line #L97 was not covered by tests
} catch (error) {
return undefined

Check warning on line 99 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L99

Added line #L99 was not covered by tests
}
})
}
public async resolveById(
templateId: string,
acceptDevRestrictions: boolean
): Promise<ProofRequestTemplate | undefined> {

Check warning on line 106 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L106

Added line #L106 was not covered by tests
if (!this.templateData) {
return (await this.resolve(acceptDevRestrictions))?.find((template) => template.id === templateId)
} else {
let templateData = this.templateData

Check warning on line 110 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L108-L110

Added lines #L108 - L110 were not covered by tests
if (acceptDevRestrictions) {
templateData = applyDevRestrictions(templateData)

Check warning on line 112 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L112

Added line #L112 was not covered by tests
}
const template = templateData.find((template) => template.id === templateId)
return template

Check warning on line 115 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L114-L115

Added lines #L114 - L115 were not covered by tests
}
}
}

export class DefaultProofBundleResolver implements ProofBundleResolverType {
private proofRequestTemplates
public constructor() {
const { proofRequestTemplates } = useConfiguration()
this.proofRequestTemplates = proofRequestTemplates ?? useProofRequestTemplates
}
public async resolve(acceptDevRestrictions: boolean): Promise<ProofRequestTemplate[]> {
return Promise.resolve(this.proofRequestTemplates(acceptDevRestrictions))
}
public async resolveById(
templateId: string,
acceptDevRestrictions: boolean
): Promise<ProofRequestTemplate | undefined> {
return Promise.resolve(
this.proofRequestTemplates(acceptDevRestrictions).find((template) => template.id === templateId)

Check warning on line 134 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L132-L134

Added lines #L132 - L134 were not covered by tests
)
}
}

export const useTemplates = (): Array<ProofRequestTemplate> => {
const [store] = useStore()
const { proofRequestTemplates } = useConfiguration()
return (proofRequestTemplates && proofRequestTemplates(store.preferences.acceptDevCredentials)) || []
const [proofRequestTemplates, setProofRequestTemplates] = useState<ProofRequestTemplate[]>([])
const { proofTemplateBaseUrl } = useConfiguration()
const resolver = useRemoteProofBundleResolver(proofTemplateBaseUrl)
useEffect(() => {
resolver.resolve(store.preferences.acceptDevCredentials).then((templates) => {
if (templates) {
setProofRequestTemplates(applyTemplateMarkers(templates))
}
})
}, [])
return proofRequestTemplates
}

export const useTemplate = (templateId: string): ProofRequestTemplate | undefined => {
const { proofRequestTemplates } = useConfiguration()
const [store] = useStore()
return (
proofRequestTemplates &&
proofRequestTemplates(store.preferences.acceptDevCredentials).find((template) => template.id === templateId)
)
const [proofRequestTemplate, setProofRequestTemplate] = useState<ProofRequestTemplate | undefined>(undefined)
const { proofTemplateBaseUrl } = useConfiguration()
const resolver = useRemoteProofBundleResolver(proofTemplateBaseUrl)
useEffect(() => {
resolver.resolveById(templateId, store.preferences.acceptDevCredentials).then((template) => {

Check warning on line 160 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L156-L160

Added lines #L156 - L160 were not covered by tests
if (template) {
setProofRequestTemplate(applyTemplateMarkers(template))

Check warning on line 162 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L162

Added line #L162 was not covered by tests
}
})
}, [])
return proofRequestTemplate

Check warning on line 166 in packages/legacy/core/App/hooks/proof-request-templates.ts

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/hooks/proof-request-templates.ts#L166

Added line #L166 was not covered by tests
}
14 changes: 9 additions & 5 deletions packages/legacy/core/App/screens/ProofRequestDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,11 @@ const ProofRequestDetails: React.FC<ProofRequestDetailsProps> = ({ route, naviga
>(undefined)

const template = useTemplate(templateId)
if (!template) {
throw new Error('Unable to find proof request template')
}

useEffect(() => {
if (!template) {
return

Check warning on line 263 in packages/legacy/core/App/screens/ProofRequestDetails.tsx

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/screens/ProofRequestDetails.tsx#L263

Added line #L263 was not covered by tests
}
const attributes = template.payload.type === ProofRequestType.AnonCreds ? template.payload.data : []

OCABundleResolver.resolve({ identifiers: { templateId }, language: i18n.language }).then((bundle) => {
Expand All @@ -282,7 +282,7 @@ const ProofRequestDetails: React.FC<ProofRequestDetailsProps> = ({ route, naviga
setMeta(metaOverlay)
setAttributes(attributes)
})
}, [templateId])
}, [templateId, template])

const onlyNumberRegex = /^\d+$/

Expand All @@ -305,6 +305,10 @@ const ProofRequestDetails: React.FC<ProofRequestDetailsProps> = ({ route, naviga
)

const useProofRequest = useCallback(async () => {
if (!template) {
return

Check warning on line 309 in packages/legacy/core/App/screens/ProofRequestDetails.tsx

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/screens/ProofRequestDetails.tsx#L309

Added line #L309 was not covered by tests
}

if (invalidPredicate) {
setInvalidPredicate({ visible: true, predicate: invalidPredicate.predicate })
return
Expand All @@ -323,7 +327,7 @@ const ProofRequestDetails: React.FC<ProofRequestDetailsProps> = ({ route, naviga
// Else redirect to the screen with connectionless request
navigation.navigate(Screens.ProofRequesting, { templateId, predicateValues: customPredicateValues })
}
}, [agent, templateId, connectionId, customPredicateValues, invalidPredicate])
}, [agent, template, templateId, connectionId, customPredicateValues, invalidPredicate])

const showTemplateUsageHistory = useCallback(async () => {
navigation.navigate(Screens.ProofRequestUsageHistory, { templateId })
Expand Down
9 changes: 4 additions & 5 deletions packages/legacy/core/App/screens/ProofRequesting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ const ProofRequesting: React.FC<ProofRequestingProps> = ({ route, navigation })
},
})

if (!template) {
throw new Error('Unable to find proof request template')
}

const createProofRequest = useCallback(async () => {
try {
setMessage(undefined)
Expand Down Expand Up @@ -165,6 +161,9 @@ const ProofRequesting: React.FC<ProofRequestingProps> = ({ route, navigation })
}, [isFocused])

useEffect(() => {
if (!template) {
return

Check warning on line 165 in packages/legacy/core/App/screens/ProofRequesting.tsx

View check run for this annotation

Codecov / codecov/patch

packages/legacy/core/App/screens/ProofRequesting.tsx#L165

Added line #L165 was not covered by tests
}
const sendAsyncProof = async () => {
if (record && record.state === DidExchangeState.Completed) {
//send haptic feedback to verifier that connection is completed
Expand All @@ -181,7 +180,7 @@ const ProofRequesting: React.FC<ProofRequestingProps> = ({ route, navigation })
}
}
sendAsyncProof()
}, [record])
}, [record, template])

useEffect(() => {
if (proofRecord && (isPresentationReceived(proofRecord) || isPresentationFailed(proofRecord))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { NetworkProvider } from '../../App/contexts/network'
import configurationContext from '../contexts/configuration'
import { useProofRequestTemplates } from '../../verifier/request-templates'
import ProofRequestDetails from '../../App/screens/ProofRequestDetails'
import { testIdWithKey } from '../../App'
import { ProofRequestType, testIdWithKey } from '../../App'
import { useTemplates, useTemplate } from '../../App/hooks/proof-request-templates'

jest.mock('react-native-permissions', () => require('react-native-permissions/mock'))
jest.mock('@react-native-community/netinfo', () => mockRNCNetInfo)
Expand All @@ -23,12 +24,47 @@ jest.mock('@react-navigation/native', () => {
return require('../../__mocks__/custom/@react-navigation/native')
})
// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.mock('react-native-localize', () => {})
jest.mock('react-native-localize', () => { })
jest.mock('react-native-device-info', () => () => jest.fn())

jest.useFakeTimers({ legacyFakeTimers: true })
jest.spyOn(global, 'setTimeout')
const templates = useProofRequestTemplates(false)

jest.mock('../../App/hooks/proof-request-templates', () => ({
useTemplates: jest.fn(),
useTemplate: jest.fn(),
}))

const templates = [
{
id: 'Aries:5:StudentFullName:0.0.1:indy',
name: 'Student full name',
description: 'Verify the full name of a student',
version: '0.0.1',
payload: {
type: ProofRequestType.AnonCreds,
data: [
{
schema: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:Student Card',
requestedAttributes: [
{
name: 'student_first_name',
restrictions:[{ cred_def_id: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:student_card' }],
},
{
name: 'student_last_name',
restrictions:[{ cred_def_id: 'XUxBrVSALWHLeycAUhrNr9:3:CL:26293:student_card' }],
},
],
},
],
},
}
]
// @ts-ignore
useTemplates.mockImplementation(() => templates)
// @ts-ignore
useTemplate.mockImplementation((id) => templates[0])
const templateId = templates[0].id
const connectionId = 'test'
const navigation = useNavigation()
Expand All @@ -50,7 +86,7 @@ describe('ProofRequestDetails Component', () => {

test('Renders correctly', async () => {
const tree = renderView({ templateId })
await act(async () => {})
await act(async () => { })
expect(tree).toMatchSnapshot()
})

Expand Down

0 comments on commit 942b833

Please sign in to comment.