Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add qr validation #11

Merged
merged 23 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
86b8e82
feat: provide validation options to qr reader component
tahmidrahman-dsi Jan 28, 2025
c73b115
chore: bump mosip package version
tahmidrahman-dsi Jan 28, 2025
244e81c
chore: bump toolkit version
tahmidrahman-dsi Jan 28, 2025
4468b17
chore: handle nid in qr data
tahmidrahman-dsi Jan 28, 2025
dd790e1
chore: add translation message
tahmidrahman-dsi Jan 28, 2025
60f86d7
Merge branch 'develop' into add-qr-validation
tahmidrahman-dsi Jan 28, 2025
7fa7f13
chore(interim): use legacy version toolkit in parallel with the lates…
tahmidrahman-dsi Jan 28, 2025
de5764d
feat: provide mapping for verified field
Zangetsu101 Jan 29, 2025
d938ebb
fix: remove opencrvs-toolkit-legacy
tahmidrahman-dsi Jan 30, 2025
aaafe4d
feat: implement id reader fields to mother, father in addition with i…
tahmidrahman-dsi Jan 30, 2025
5de1274
fix: remove skip and update snapshot
tahmidrahman-dsi Jan 30, 2025
fd06f49
fix: unintended update flag
tahmidrahman-dsi Jan 30, 2025
59f5e6b
chore: pre-pop fields of mother and father section
tahmidrahman-dsi Jan 30, 2025
f2f4546
chore: update form configs
tahmidrahman-dsi Jan 31, 2025
33afcb2
fix: error message
tahmidrahman-dsi Jan 31, 2025
2661b08
chore: bump mosip package version
tahmidrahman-dsi Jan 31, 2025
60ce05a
fix: update copies
tahmidrahman-dsi Feb 3, 2025
dfb6de3
feat: add handlers for review & approval actions
Zangetsu101 Jan 29, 2025
151c938
Merge pull request #13 from opencrvs/online-verification
tahmidrahman-dsi Feb 3, 2025
b21435d
feat: authenticated status related messages
tahmidrahman-dsi Feb 3, 2025
ed67df3
fix: typo with ids
tahmidrahman-dsi Feb 4, 2025
16a38e3
fix: typo
tahmidrahman-dsi Feb 4, 2025
fb88f6d
fix: add missing env vars
tahmidrahman-dsi Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion infrastructure/docker-compose.deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ services:
- LOCALE=en
- ESIGNET_USERINFO_URL=${ESIGNET_USERINFO_URL:-}
- OIDP_CLIENT_PRIVATE_KEY=${OIDP_CLIENT_PRIVATE_KEY:-}
- ESIGNET_TOKEN_URL=${ESIGNET_TOKEN_URL:-}
- OIDP_JWT_AUD_CLAIM=${OIDP_JWT_AUD_CLAIM:-}
deploy:
replicas: 1
labels:
Expand Down Expand Up @@ -1064,7 +1066,7 @@ services:
image: ghcr.io/opencrvs/mosip-mock:${MOSIP_API_VERSION}
environment:
- NODE_ENV=production
- OPENCRVS_MOSIP_SERVER_URL=https://mosip-api.{{hostname}}/webhooks/mosip
- OPENCRVS_MOSIP_API_URL=https://mosip-api.{{hostname}}/webhooks/mosip
- SENDER_EMAIL_ADDRESS=${SENDER_EMAIL_ADDRESS:-}
- ALERT_EMAIL=${ALERT_EMAIL:-}
- SMTP_HOST=${SMTP_HOST:-}
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
"@hapi/boom": "^9.1.1",
"@hapi/hapi": "^20.0.1",
"@hapi/inert": "^6.0.3",
"@opencrvs/mosip": "^1.7.0-alpha.13",
"@opencrvs/toolkit": "0.0.32-jr",
"@opencrvs/mosip": "^1.7.0-alpha.17",
"@opencrvs/toolkit": "0.0.33",
"@types/chalk": "^2.2.0",
"@types/csv2json": "^1.4.0",
"@types/fhir": "^0.0.30",
Expand Down Expand Up @@ -122,4 +122,4 @@
"minimist": "^1.2.2",
"acorn": "^6.4.1"
}
}
}
123 changes: 55 additions & 68 deletions src/form/birth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/

import { Event, ISerializedForm, SerializedFormField } from '../types/types'
import { Event, ISerializedForm } from '../types/types'
import { formMessageDescriptors } from '../common/messages'
import { informantType } from './required-fields'
import {
Expand Down Expand Up @@ -76,23 +76,16 @@ import {
} from './required-sections'
import { certificateHandlebars } from './certificate-handlebars'
import { getSectionMapping } from '@countryconfig/utils/mapping/section/birth/mapping-utils'
import { getCommonSectionMapping } from '@countryconfig/utils/mapping/field-mapping-utils'
import {
getCommonSectionMapping,
getCustomFieldMapping
} from '@countryconfig/utils/mapping/field-mapping-utils'
import { getReasonForLateRegistration } from '../custom-fields'
import { getIDNumberFields, getIDType } from '../custom-fields'
import {
esignet,
esignetCallback,
idReader,
idVerificationFields,
qr
} from '@opencrvs/mosip'
import { getGenderCustom } from './custom-fields'
import {
ESIGNET_TOKEN_URL,
MOSIP_API_USERINFO_URL,
OPENID_PROVIDER_CLAIMS,
OPENID_PROVIDER_CLIENT_ID
} from '@countryconfig/constants'
import { idReaderFields, getInitialValueFromIDReader } from '@opencrvs/mosip'
import { esignetConfig, qrCodeConfig } from '../common/id-reader-configurations'

// import { createCustomFieldExample } from '../custom-fields'

// ======================= FORM CONFIGURATION =======================
Expand Down Expand Up @@ -233,64 +226,40 @@ export const birthForm: ISerializedForm = {
fields: [
informantType, // Required field.
otherInformantType(Event.Birth), // Required field.
idReader(
...idReaderFields(
'birth',
'informant',
informantFirstNameConditionals
.concat(hideIfInformantMotherOrFather)
.concat({
action: 'hide',
expression: '!!$form?.verified'
}),
[
qr(),
esignet(
ESIGNET_TOKEN_URL,
OPENID_PROVIDER_CLIENT_ID,
OPENID_PROVIDER_CLAIMS,
'esignet',
'esignetCallback'
)
]
) as SerializedFormField,
esignetCallback({
fieldName: 'esignetCallback',
mosipAPIUserInfoUrl: MOSIP_API_USERINFO_URL,
openIdProviderClientId: OPENID_PROVIDER_CLIENT_ID
}) as SerializedFormField,
...(idVerificationFields(
'birth',
'informant'
) as SerializedFormField[]),
qrCodeConfig,
esignetConfig,
getCustomFieldMapping(
`birth.informant.informant-view-group.verified`
),
informantFirstNameConditionals.concat(
hideIfInformantMotherOrFather
)
),
getFirstNameField(
'informantNameInEnglish',
informantFirstNameConditionals.concat(
hideIfInformantMotherOrFather
),
certificateHandlebars.informantFirstName,
{
dependsOn: ['idReader', 'esignetCallback'],
expression:
'$form?.idReader?.firstName || $form?.esignetCallback?.data?.firstName || ""'
}
getInitialValueFromIDReader('firstName')
), // Required field. In Farajaland, we have built the option to integrate with MOSIP. So we have different conditionals for each name to check MOSIP responses. You could always refactor firstNamesEng for a basic setup
getFamilyNameField(
'informantNameInEnglish',
informantFamilyNameConditionals.concat(
hideIfInformantMotherOrFather
),
certificateHandlebars.informantFamilyName,
{
dependsOn: ['idReader', 'esignetCallback'],
expression:
'$form?.idReader?.familyName || $form?.esignetCallback?.data?.familyName || ""'
}
getInitialValueFromIDReader('familyName')
), // Required field.
getGenderCustom(
'birth',
'informant',
[],
getInitialValueFromIDReader('gender')
), // Required field.
getGenderCustom('birth', 'informant', [], {
dependsOn: ['idReader', 'esignetCallback'],
expression:
'$form?.idReader?.gender || $form?.esignetCallback?.data?.gender || ""'
}),
getBirthDate(
'informantBirthDate',
informantBirthDateConditionals.concat(
Expand All @@ -307,11 +276,7 @@ export const birthForm: ISerializedForm = {
}
],
certificateHandlebars.informantBirthDate,
{
dependsOn: ['idReader', 'esignetCallback'],
expression:
'$form?.idReader?.birthDate || $form?.esignetCallback?.data?.birthDate || ""'
}
getInitialValueFromIDReader('birthDate')
), // Required field.
exactDateOfBirthUnknown(hideIfInformantMotherOrFather),
getAgeOfIndividualInYears(
Expand Down Expand Up @@ -370,21 +335,32 @@ export const birthForm: ISerializedForm = {
mothersDetailsExistConditionals
),
getReasonNotExisting(certificateHandlebars.motherReasonNotApplying), // Strongly recommend is required if you want to register abandoned / orphaned children!
...idReaderFields(
'birth',
'mother',
qrCodeConfig,
esignetConfig,
getCustomFieldMapping(`birth.mother.mother-view-group.verified`),
detailsExist
),
getFirstNameField(
'motherNameInEnglish',
motherFirstNameConditionals,
certificateHandlebars.motherFirstName
certificateHandlebars.motherFirstName,
getInitialValueFromIDReader('firstName')
), // Required field.
getFamilyNameField(
'motherNameInEnglish',
motherFamilyNameConditionals,
certificateHandlebars.motherFamilyName
certificateHandlebars.motherFamilyName,
getInitialValueFromIDReader('familyName')
), // Required field.
getBirthDate(
'motherBirthDate',
mothersBirthDateConditionals,
parentsBirthDateValidators,
certificateHandlebars.motherBirthDate
certificateHandlebars.motherBirthDate,
getInitialValueFromIDReader('birthDate')
), // Required field.
exactDateOfBirthUnknown(detailsExistConditional),
getAgeOfIndividualInYears(
Expand Down Expand Up @@ -449,21 +425,32 @@ export const birthForm: ISerializedForm = {
fathersDetailsExistConditionals
),
getReasonNotExisting('fatherReasonNotApplying'), // Strongly recommend is required if you want to register abandoned / orphaned children!
...idReaderFields(
'birth',
'father',
qrCodeConfig,
esignetConfig,
getCustomFieldMapping(`birth.father.father-view-group.verified`),
detailsExist
),
getFirstNameField(
'fatherNameInEnglish',
fatherFirstNameConditionals,
certificateHandlebars.fatherFirstName
certificateHandlebars.fatherFirstName,
getInitialValueFromIDReader('firstName')
), // Required field.
getFamilyNameField(
'fatherNameInEnglish',
fatherFamilyNameConditionals,
certificateHandlebars.fatherFamilyName
certificateHandlebars.fatherFamilyName,
getInitialValueFromIDReader('familyName')
), // Required field.
getBirthDate(
'fatherBirthDate',
fathersBirthDateConditionals,
parentsBirthDateValidators,
certificateHandlebars.fatherBirthDate
certificateHandlebars.fatherBirthDate,
getInitialValueFromIDReader('birthDate')
), // Required field.
exactDateOfBirthUnknown(detailsExistConditional),
getAgeOfIndividualInYears(
Expand Down
45 changes: 45 additions & 0 deletions src/form/common/id-reader-configurations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* OpenCRVS is also distributed under the terms of the Civil Registration
* & Healthcare Disclaimer located at http://opencrvs.org/license.
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/

import { and, objectHasProperty } from '@opencrvs/toolkit/conditionals'
import {
ESIGNET_TOKEN_URL,
MOSIP_API_USERINFO_URL,
OPENID_PROVIDER_CLIENT_ID
} from '@countryconfig/constants'

export const qrCodeConfig = {
validation: {
rule: and(
objectHasProperty('firstName', 'string'),
objectHasProperty('familyName', 'string'),
objectHasProperty('gender', 'string'),
objectHasProperty('birthDate', 'string'),
objectHasProperty('nid', 'string')
),
errorMessage: {
defaultMessage: 'This QR code is not recognised. Please try again.',
description: 'Error message for QR code validation',
id: 'form.field.qr.validation.error'
}
}
}

export const esignetConfig = {
fieldName: 'esignet',
esignetAuthUrl: ESIGNET_TOKEN_URL,
openIdProviderClientId: OPENID_PROVIDER_CLIENT_ID,
openIdProviderClaims: undefined,
callback: {
fieldName: 'esignetCallback',
mosipAPIUserInfoUrl: MOSIP_API_USERINFO_URL
}
}
19 changes: 17 additions & 2 deletions src/form/custom-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ export function getIDType(
description: 'A form field that asks for the type of ID.',
defaultMessage: 'Type of ID'
},
initialValue: '',
initialValue: {
dependsOn: ['idReader'],
expression: '!!$form?.idReader?.nid? "NATIONAL_ID" : ""'
},
validator: [],
mapping: getCustomFieldMapping(fieldId),
placeholder: formMessageDescriptors.formSelectPlaceholder,
Expand All @@ -173,6 +176,18 @@ function getValidators(configCase: string, idValue: IDType) {
return []
}

function initialValuesForIDType(idType: IDType) {
if (idType === 'NATIONAL_ID') {
return {
dependsOn: ['idReader'],
expression:
'$form?.idReader?.nid || $form?.esignetCallback?.data?.nid || ""'
}
} else {
return ''
}
}

export function getIDNumber(
sectionId: string,
idValue: IDType,
Expand All @@ -194,7 +209,7 @@ export function getIDNumber(
description: 'A form field that asks for the id number.',
defaultMessage: 'ID number'
},
initialValue: '',
initialValue: initialValuesForIDType(idValue),
validator: validators,
mapping: {
template: {
Expand Down
Loading
Loading