Skip to content

Commit

Permalink
Reworked UI (#92)
Browse files Browse the repository at this point in the history
* Stepper approach to define presentation request. First select scheme, then select presentation scenario and attestation details and in the end specify the attributes

* Popup dialog for selecting attestation attributes

* Moved scheme config to top menu, present summary of presentation request, init transaction with collected

* Added badges to indicate number of attributes selected

* Added link for custom request preparation

* Improvements

* Removed un-used routes, moved selectable attributes component to presentation preparation module, clean up un-used components

* Removed un-used routes, moved selectable attributes component to presentation preparation module, clean up un-used components

* When re-opening attributes selection popup, remember previous selection, bug fixes

* Display unsupported formats as disabled options, minor fixes

* Replaced qrcodejs with angularx-qrcode for QR code rendering

* Bump version to 0.6.0
  • Loading branch information
vafeini authored Nov 4, 2024
1 parent d5cfb42 commit 835f3bc
Show file tree
Hide file tree
Showing 73 changed files with 1,321 additions and 968 deletions.
5 changes: 1 addition & 4 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@
"includePaths": [
"src/template.sass"
]
},
"scripts": [
"./node_modules/qrcodejs/qrcode.min.js"
]
}
},
"configurations": {
"production": {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "verifier-ui",
"version": "0.5.2-SNAPSHOT",
"version": "0.6.0",
"scripts": {
"ng": "ng",
"start": "npm run config && ng serve --proxy-config src/proxy.conf.json",
Expand Down Expand Up @@ -37,7 +37,7 @@
"jsonpath-plus": "^9.0.0",
"jwt-decode": "3.1.2",
"nofilter": "^4.0.2",
"qrcodejs": "^1.0.0",
"angularx-qrcode": "^15.0.1",
"rxjs": "~7.8.0",
"stream-browserify": "^3.0.0",
"thememirror": "^2.0.1",
Expand Down
1 change: 0 additions & 1 deletion src/QRCode.d.ts

This file was deleted.

23 changes: 8 additions & 15 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,18 @@ import {NavigateService} from '@core/services/navigate.service';
import {VerifierEndpointService} from "@core/services/verifier-endpoint.service";

const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadComponent: () => import('./features/home/components/home/home.component').then(c => c.HomeComponent) },
{ path: '',
redirectTo: 'home',
pathMatch: 'full' },
{ path: 'home', loadComponent: () => import('@features/presentation-request-preparation/home/home.component')
.then(c => c.HomeComponent) },
{ path: 'custom-request',
loadChildren: () => import('@features/custom-presentation-request/custom-presentation-request.module').
then(m => m.CustomPresentationRequestModule )},
{ path: 'selectable',
loadChildren: () => import('@features/selectable-presentation/selectable-presentation.module').
then(m => m.SelectablePresentationModule )
},
{ path: 'invoke-wallet',
{ path: 'invoke-wallet',
loadChildren: () => import('@features/invoke-wallet/invoke-wallet.module').
then(m => m.InvokeWalletModule)
},
{ path: 'mdl-selectable',
loadChildren: () => import('@features/selectable-presentation/selectable-presentation.module').
then(m => m.SelectablePresentationModule ),
},
{
path: 'get-wallet-code',
then(m => m.InvokeWalletModule) },
{ path: 'get-wallet-code',
loadComponent: () => import('./features/wallet-redirect/wallet-redirect.component').then(c => c.WalletRedirectComponent),
providers: [VerifierEndpointService, NavigateService],
resolve: {
Expand Down
141 changes: 141 additions & 0 deletions src/app/core/constants/attestations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import {Attestation} from "@core/models/attestation/Attestation";
import {AttestationType} from "@core/models/attestation/AttestationType";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";

export const PID_ATTESTATION: Attestation = {
name: "Person Identification Data (PID)",
type: AttestationType.PID,
dataSet: [
{ identifier: 'family_name', attribute: 'Family name'},
{ identifier: 'given_name', attribute: 'Given name'},
{ identifier: 'birth_date', attribute: 'Birthdate'},
{ identifier: 'age_over_18', attribute: 'Age over 18'},
{ identifier: 'age_in_years', attribute: 'Age in years'},
{ identifier: 'age_birth_year', attribute: 'Age birth year'},
{ identifier: 'family_name_birth', attribute: 'Family name birth'},
{ identifier: 'given_name_birth', attribute: 'Given name birth'},
{ identifier: 'birth_place', attribute: 'Birth place'},
{ identifier: 'birth_country', attribute: 'Birth country'},
{ identifier: 'birth_state', attribute: 'Birth state'},
{ identifier: 'birth_city', attribute: 'Birth city'},
{ identifier: 'resident_address', attribute: 'Resident address'},
{ identifier: 'resident_country', attribute: 'Resident country'},
{ identifier: 'resident_state', attribute: 'Resident state'},
{ identifier: 'resident_city', attribute: 'Resident city'},
{ identifier: 'resident_postal_code', attribute: 'Resident postal code'},
{ identifier: 'resident_street', attribute: 'Resident street'},
{ identifier: 'resident_house_number', attribute: 'Resident house number'},
{ identifier: 'gender', attribute: 'Gender'},
{ identifier: 'nationality', attribute: 'Nationality'},
{ identifier: 'issuance_date', attribute: 'Issuance date'},
{ identifier: 'expiry_date', attribute: 'Expiry date'},
{ identifier: 'issuing_authority', attribute: 'Issuing authority'},
{ identifier: 'document_number', attribute: 'Document number'},
{ identifier: 'administrative_number', attribute: 'Administrative number'},
{ identifier: 'issuing_country', attribute: 'Issuing country'},
{ identifier: 'issuing_jurisdiction', attribute: 'Issuing jurisdiction'}
]
}

export const MDL_ATTESTATION: Attestation = {
name: "Mobile Driving Licence (MDL)",
type: AttestationType.MDL,
dataSet: [
{ identifier: 'family_name', attribute: 'Family name' },
{ identifier: 'given_name', attribute: 'Given name'},
{ identifier: 'birth_date', attribute: 'Birthdate'},
{ identifier: 'issue_date', attribute: 'Issue date'},
{ identifier: 'expiry_date', attribute: 'Expiry date'},
{ identifier: 'age_over_18', attribute: 'Age over 18'},
{ identifier: 'age_over_21', attribute: 'Age over 21'},
{ identifier: 'age_in_years', attribute: 'Age in years'},
{ identifier: 'age_birth_year', attribute: 'Age birth year'},
{ identifier: 'issuing_authority', attribute: 'Issuing authority'},
{ identifier: 'document_number', attribute: 'Document number'},
{ identifier: 'portrait', attribute: 'Portrait'},
{ identifier: 'driving_privileges', attribute: 'Driving privileges'},
{ identifier: 'un_distinguishing_sign', attribute: 'Un-distinguishing sign'},
{ identifier: 'administrative_number', attribute: 'Administrative number'},
{ identifier: 'sex', attribute: 'Sex'},
{ identifier: 'height', attribute: 'Height'},
{ identifier: 'weight', attribute: 'Weight'},
{ identifier: 'eye_colour', attribute: 'Eye colour'},
{ identifier: 'hair_colour', attribute: 'Hair colour'},
{ identifier: 'birth_place', attribute: 'Birth place'},
{ identifier: 'resident_address', attribute: 'Resident address'},
{ identifier: 'portrait_capture_date', attribute: 'Portrait capture date'},
{ identifier: 'nationality', attribute: 'Nationality'},
{ identifier: 'resident_city', attribute: 'Resident city'},
{ identifier: 'resident_state', attribute: 'Resident state'},
{ identifier: 'resident_postal_code', attribute: 'Resident postal code'},
{ identifier: 'resident_country', attribute: 'Resident country'},
{ identifier: 'family_name_national_character', attribute: 'Family name national character'},
{ identifier: 'given_name_national_character', attribute: 'Given name national character'},
{ identifier: 'signature_usual_mark', attribute: 'Signature usual mark'}
]
}

export const AGE_OVER_18_ATTESTATION: Attestation = {
name: "Age Over 18",
type: AttestationType.AGE_OVER_18,
dataSet: [
{ identifier: 'age_over_18', attribute: 'Age over 18'},
{ identifier: 'user_pseudonym', attribute: 'User pseudonym'},
{ identifier: 'issuance_date', attribute: 'Issuance date'},
{ identifier: 'expiry_date', attribute: 'Expiry date'},
{ identifier: 'issuing_authority', attribute: 'Issuing authority'},
{ identifier: 'issuing_jurisdiction', attribute: 'Issuing jurisdiction'},
{ identifier: 'issuing_country', attribute: 'Issuing country'}
]
}

export const PHOTO_ID_ATTESTATION: Attestation = {
name: "Photo ID",
type: AttestationType.PHOTO_ID,
dataSet: [
{ identifier: 'portrait', attribute: 'Portrait'},
{ identifier: 'portrait_capture_date', attribute: 'Portrait capture date'},
{ identifier: 'person_id', attribute: 'Person id'},
{ identifier: 'family_name', attribute: 'Family_name'},
{ identifier: 'given_name', attribute: 'Given name'},
{ identifier: 'birth_date', attribute: 'Birth date'},
{ identifier: 'age_over_18', attribute: 'Age over 18'},
{ identifier: 'age_over_NN', attribute: 'Age over NN'},
{ identifier: 'age_in_years', attribute: 'Age in years'},
{ identifier: 'age_birth_year', attribute: 'Age birth year'},
{ identifier: 'family_name_birth', attribute: 'Family name birth'},
{ identifier: 'given_name_birth', attribute: 'Given name birth'},
{ identifier: 'birth_place', attribute: 'Birth place'},
{ identifier: 'birth_country', attribute: 'Birth country'},
{ identifier: 'birth_state', attribute: 'Birth state'},
{ identifier: 'birth_city', attribute: 'Birth city'},
{ identifier: 'resident_address', attribute: 'Resident address'},
{ identifier: 'resident_country', attribute: 'Resident country'},
{ identifier: 'resident_state', attribute: 'Resident state'},
{ identifier: 'resident_city', attribute: 'Resident city'},
{ identifier: 'resident_postal_code', attribute: 'Resident postal code'},
{ identifier: 'resident_street', attribute: 'Resident street'},
{ identifier: 'resident_house_number', attribute: 'Resident house number'},
{ identifier: 'gender', attribute: 'Gender'},
{ identifier: 'nationality', attribute: 'Nationality'},
{ identifier: 'issuance_date', attribute: 'Issuance date'},
{ identifier: 'expiry_date', attribute: 'Expiry date'},
{ identifier: 'issuing_authority', attribute: 'Issuing authority'},
{ identifier: 'document_number', attribute: 'Document number'},
{ identifier: 'administrative_number', attribute: 'Administrative number'},
{ identifier: 'issuing_country', attribute: 'Issuing country'},
{ identifier: 'issuing_jurisdiction', attribute: 'Issuing jurisdiction'}
]
}

export const SUPPORTED_ATTESTATIONS: { [id: string]: Attestation } = {
"pid": PID_ATTESTATION,
"mdl": MDL_ATTESTATION,
"photo_id": PHOTO_ID_ATTESTATION,
"age_over_18": AGE_OVER_18_ATTESTATION,
}

export const SUPPORTED_FORMATS: AttestationFormat[] = [
AttestationFormat.MSO_MDOC
]

File renamed without changes.
54 changes: 54 additions & 0 deletions src/app/core/constants/presentation-scenarios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {PresentationScenario} from "@features/presentation-request-preparation/models/PresentationScenario";
import {AttributeSelectionMethod} from "@features/presentation-request-preparation/models/ScenarioAttestation";
import {AttestationType} from "@core/models/attestation/AttestationType";

export const PID_AUTHENTICATION_SCENARIO: PresentationScenario = {
name: "PID Authentication",
attestations: [{
attestationType: AttestationType.PID,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}]
}

export const MDL_AUTHENTICATION_SCENARIO: PresentationScenario = {
name: "MDL Authentication",
attestations: [{
attestationType: AttestationType.MDL,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}]
}

export const AGE_VERIFICATION_SCENARIO: PresentationScenario = {
name: "Age Verification",
attestations: [{
attestationType: AttestationType.AGE_OVER_18,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE]
}, {
attestationType: AttestationType.PID,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE]
}]
}

export const MULTIPLE_ATTESTATIONS_SCENARIO: PresentationScenario = {
name: "Multiple Attestations",
attestations: [{
attestationType: AttestationType.AGE_OVER_18,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}, {
attestationType: AttestationType.PHOTO_ID,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}, {
attestationType: AttestationType.PID,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}, {
attestationType: AttestationType.MDL,
attributeSelectionMethods: [AttributeSelectionMethod.SELECTABLE, AttributeSelectionMethod.ALL_ATTRIBUTES]
}]
}

export const PRESENTATION_SCENARIOS: PresentationScenario[] = [
PID_AUTHENTICATION_SCENARIO,
MDL_AUTHENTICATION_SCENARIO,
AGE_VERIFICATION_SCENARIO,
MULTIPLE_ATTESTATIONS_SCENARIO
]
106 changes: 25 additions & 81 deletions src/app/core/data/MsoMdocDocuments.ts
Original file line number Diff line number Diff line change
@@ -1,93 +1,37 @@
import {MsoMdoc} from "@core/models/MsoMdoc";
import {MsoMdocAttestation} from "@core/models/attestation/MsoMdocAttestation";
import {AGE_OVER_18_ATTESTATION, MDL_ATTESTATION, PHOTO_ID_ATTESTATION, PID_ATTESTATION} from "@core/constants/attestations";

/* eslint-disable quotes */
export const MDL_MSO_MDOC: MsoMdoc = {
name: 'Mobile Driving Licence',
export const MDL_MSO_MDOC: MsoMdocAttestation = {
attestation: MDL_ATTESTATION,
doctype: 'org.iso.18013.5.1.mDL',
namespace: 'org.iso.18013.5.1',
attributes: [
{ value: 'family_name', text: 'Family name' },
{ value: 'given_name', text: 'Given name'},
{ value: 'birth_date', text: 'Birthdate'},
{ value: 'issue_date', text: 'Issue date'},
{ value: 'expiry_date', text: 'Expiry date'},
{ value: 'age_over_18', text: 'Age over 18'},
{ value: 'age_over_21', text: 'Age over 21'},
{ value: 'age_in_years', text: 'Age in years'},
{ value: 'age_birth_year', text: 'Age birth year'},
{ value: 'issuing_authority', text: 'Issuing authority'},
{ value: 'document_number', text: 'Document number'},
{ value: 'portrait', text: 'Portrait'},
{ value: 'driving_privileges', text: 'Driving privileges'},
{ value: 'un_distinguishing_sign', text: 'Un-distinguishing sign'},
{ value: 'administrative_number', text: 'Administrative number'},
{ value: 'sex', text: 'Sex'},
{ value: 'height', text: 'Height'},
{ value: 'weight', text: 'Weight'},
{ value: 'eye_colour', text: 'Eye colour'},
{ value: 'hair_colour', text: 'Hair colour'},
{ value: 'birth_place', text: 'Birth place'},
{ value: 'resident_address', text: 'Resident address'},
{ value: 'portrait_capture_date', text: 'Portrait capture date'},
{ value: 'nationality', text: 'Nationality'},
{ value: 'resident_city', text: 'Resident city'},
{ value: 'resident_state', text: 'Resident state'},
{ value: 'resident_postal_code', text: 'Resident postal code'},
{ value: 'resident_country', text: 'Resident country'},
{ value: 'family_name_national_character', text: 'Family name national character'},
{ value: 'given_name_national_character', text: 'Given name national character'},
{ value: 'signature_usual_mark', text: 'Signature usual mark'}]
namespace: 'org.iso.18013.5.1'
}

/* eslint-disable quotes */
export const PID_MSO_MDOC: MsoMdoc = {
name: 'EUDI PID',
export const PID_MSO_MDOC: MsoMdocAttestation = {
attestation: PID_ATTESTATION,
doctype: 'eu.europa.ec.eudi.pid.1',
namespace: 'eu.europa.ec.eudi.pid.1',
attributes: [
{ value: 'family_name', text: 'Family name'},
{ value: 'given_name', text: 'Given name'},
{ value: 'birth_date', text: 'Birthdate'},
{ value: 'age_over_18', text: 'Age over 18'},
{ value: 'age_in_years', text: 'Age in years'},
{ value: 'age_birth_year', text: 'Age birth year'},
{ value: 'family_name_birth', text: 'Family name birth'},
{ value: 'given_name_birth', text: 'Given name birth'},
{ value: 'birth_place', text: 'Birth place'},
{ value: 'birth_country', text: 'Birth country'},
{ value: 'birth_state', text: 'Birth state'},
{ value: 'birth_city', text: 'Birth city'},
{ value: 'resident_address', text: 'Resident address'},
{ value: 'resident_country', text: 'Resident country'},
{ value: 'resident_state', text: 'Resident state'},
{ value: 'resident_city', text: 'Resident city'},
{ value: 'resident_postal_code', text: 'Resident postal code'},
{ value: 'resident_street', text: 'Resident street'},
{ value: 'resident_house_number', text: 'Resident house number'},
{ value: 'gender', text: 'Gender'},
{ value: 'nationality', text: 'Nationality'},
{ value: 'issuance_date', text: 'Issuance date'},
{ value: 'expiry_date', text: 'Expiry date'},
{ value: 'issuing_authority', text: 'Issuing authority'},
{ value: 'document_number', text: 'Document number'},
{ value: 'administrative_number', text: 'Administrative number'},
{ value: 'issuing_country', text: 'Issuing country'},
{ value: 'issuing_jurisdiction', text: 'Issuing jurisdiction'}
]
namespace: 'eu.europa.ec.eudi.pid.1'
}

/* eslint-disable quotes */
export const AGE_OVER_18_MSO_MDOC: MsoMdoc = {
name: 'Age Over 18 Attestation',
export const AGE_OVER_18_MSO_MDOC: MsoMdocAttestation = {
attestation: AGE_OVER_18_ATTESTATION,
doctype: 'eu.europa.ec.eudi.pseudonym.age_over_18.1',
namespace: 'eu.europa.ec.eudi.pseudonym.age_over_18.1',
attributes: [
{ value: 'age_over_18', text: 'Age over 18'},
{ value: 'user_pseudonym', text: 'User pseudonym'},
{ value: 'issuance_date', text: 'Issuance date'},
{ value: 'expiry_date', text: 'Expiry date'},
{ value: 'issuing_authority', text: 'Issuing authority'},
{ value: 'issuing_jurisdiction', text: 'Issuing jurisdiction'},
{ value: 'issuing_country', text: 'Issuing country'}
]
namespace: 'eu.europa.ec.eudi.pseudonym.age_over_18.1'
}

/* eslint-disable quotes */
export const PHOTO_ID_MSO_MDOC: MsoMdocAttestation = {
attestation: PHOTO_ID_ATTESTATION,
doctype: 'org.iso.23220.2.photoid.1',
namespace: 'org.iso.23220.2.photoid.1'
}

export const MSO_MDOC_BY_TYPE: { [id: string]: MsoMdocAttestation } = {
"pid": PID_MSO_MDOC,
"mdl": MDL_MSO_MDOC,
"photo_id": PHOTO_ID_MSO_MDOC,
"age_over_18": AGE_OVER_18_MSO_MDOC,
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
<button mat-menu-item>
<a id="inspectLogs" (click)="inspectLogs()">Inspect transaction logs</a>
</button>
<button mat-menu-item>
<a id="customScheme" (click)="changeCustomScheme()">Change default scheme</a>
</button>
</mat-menu>
Loading

0 comments on commit 835f3bc

Please sign in to comment.