From d17fdcde629ae4779aed2cb1718c10e98d796678 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 12:59:54 +0545 Subject: [PATCH 01/23] refactor: Add missing issuer in discover #3046 --- lib/credentials/cubit/credentials_cubit.dart | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/credentials/cubit/credentials_cubit.dart b/lib/credentials/cubit/credentials_cubit.dart index c96a0856f..53ab1f5f1 100644 --- a/lib/credentials/cubit/credentials_cubit.dart +++ b/lib/credentials/cubit/credentials_cubit.dart @@ -1058,7 +1058,7 @@ class CredentialsCubit extends Cubit { /// We always have the associated Adress credential /// in the discover since "Do not remove the GET a crypto account - /// in the Discover #2649" + /// in the Discover #2649" if (isCurrentBlockchainAccount) { /// if already added do not add @@ -1073,9 +1073,7 @@ class CredentialsCubit extends Cubit { /// do not add if format matched /// there can be same credentials with different format } else { - if (!alreadyAdded) { - requiredCreds.add(credInfo); - } + requiredCreds.add(credInfo); } } } @@ -1087,14 +1085,7 @@ class CredentialsCubit extends Cubit { !isCurrentBlockchainAccount) { /// do not add if current blockchain acccount does not match } else { - final alreadyAdded = requiredCreds.any( - (item) => - item.credentialType == credInfo.credentialType && - item.formatType == credInfo.formatType, - ); - if (!alreadyAdded) { - requiredCreds.add(credInfo); - } + requiredCreds.add(credInfo); } } } From 3ab5466f29fe9ece36da12d6954266f77fa8fd43 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 13:10:20 +0545 Subject: [PATCH 02/23] feat: Remove registration for developer mode #3008 --- lib/app/shared/helper_functions/helper_functions.dart | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 8911a74ce..e37091348 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -1428,12 +1428,6 @@ Future getFormattedStringOIDC4VPSIOPV2({ uri: Uri.parse(url), ); - final registration = Uri.parse(url).queryParameters['registration']; - - final registrationMap = registration != null - ? jsonDecode(registration) as Map - : null; - final data = ''' SCHEME : ${getSchemeFromUrl(url)}\n AUTHORIZATION REQUEST : @@ -1441,9 +1435,7 @@ ${response != null ? const JsonEncoder.withIndent(' ').convert(response) : Uri. CLIENT METADATA : ${clientMetaData != null ? const JsonEncoder.withIndent(' ').convert(clientMetaData) : 'None'}\n PRESENTATION DEFINITION : -${presentationDefinition != null ? const JsonEncoder.withIndent(' ').convert(presentationDefinition) : 'None'}\n -REGISTRATION : -${registrationMap != null ? const JsonEncoder.withIndent(' ').convert(registrationMap) : 'None'} +${presentationDefinition != null ? const JsonEncoder.withIndent(' ').convert(presentationDefinition) : 'None'} '''; return data; From b67c1cd9ca6d5aa8a655b09957ccb5bc1358ee69 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 14:03:35 +0545 Subject: [PATCH 03/23] feat: Fetch verifier metadata from link #3009 --- lib/app/shared/constants/parameters.dart | 5 ++ .../view/oidc4vc_settings_menu.dart | 11 +-- lib/dashboard/drawer/ssi/ssi.dart | 1 + .../verifiers_metadata.dart | 1 + .../view/verifiers_metadata_page.dart | 72 +++++++++++++++++++ lib/dashboard/json_viewer/json_viewer.dart | 1 + .../json_viewer/view/json_viewer_page.dart | 42 +---------- .../widget/json_viewer_widget.dart | 49 +++++++++++++ lib/dashboard/json_viewer/widget/widget.dart | 1 + 9 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 lib/dashboard/drawer/ssi/verifiers_metadata/verifiers_metadata.dart create mode 100644 lib/dashboard/drawer/ssi/verifiers_metadata/view/verifiers_metadata_page.dart create mode 100644 lib/dashboard/json_viewer/widget/json_viewer_widget.dart create mode 100644 lib/dashboard/json_viewer/widget/widget.dart diff --git a/lib/app/shared/constants/parameters.dart b/lib/app/shared/constants/parameters.dart index 33ce7da44..c6a2580a6 100644 --- a/lib/app/shared/constants/parameters.dart +++ b/lib/app/shared/constants/parameters.dart @@ -118,6 +118,11 @@ class Parameters { // 'https://app.altme.io/wallet_issuer' for altme static const String walletIssuer = 'https://app.altme.io/wallet_issuer'; + // 'https://app.talao.co/wallet-issuer/.well-known/openid-configuration'for talao + // 'https://app.altme.io/wallet-issuer/.well-known/openid-configuration' for altme + static const String walletMetadataForVerifier = + 'https://app.altme.io/wallet-issuer/.well-known/openid-configuration'; + static const DidKeyType didKeyTypeForEbsiV3 = DidKeyType.ebsiv3; static const DidKeyType didKeyTypeForEbsiV4 = DidKeyType.ebsiv4; static const DidKeyType didKeyTypeForDefault = DidKeyType.edDSA; diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart index c712edd42..d3ab5f826 100644 --- a/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; +import 'package:altme/dashboard/drawer/ssi/verifiers_metadata/view/verifiers_metadata_page.dart'; import 'package:flutter/material.dart'; class Oidc4vcSettingMenu extends StatelessWidget { @@ -65,15 +66,7 @@ class Oidc4vcSettingMenuView extends StatelessWidget { DrawerItem( title: 'Wallet metadata for verifiers', onTap: () { - final value = const JsonEncoder.withIndent(' ').convert( - ConstantsJson.walletMetadataForVerifiers, - ); - Navigator.of(context).push( - JsonViewerPage.route( - title: 'Wallet metadata for verifiers', - data: value, - ), - ); + Navigator.of(context).push(VerifiersMetadataPage.route()); }, ), ], diff --git a/lib/dashboard/drawer/ssi/ssi.dart b/lib/dashboard/drawer/ssi/ssi.dart index d63269992..c774fa13f 100644 --- a/lib/dashboard/drawer/ssi/ssi.dart +++ b/lib/dashboard/drawer/ssi/ssi.dart @@ -2,3 +2,4 @@ export 'manage_did/manage_did.dart'; export 'oidc4vc_settngs/oidc4vc_settings.dart'; export 'src/src.dart'; export 'trust_framework/trust_framework.dart'; +export 'verifiers_metadata/verifiers_metadata.dart'; diff --git a/lib/dashboard/drawer/ssi/verifiers_metadata/verifiers_metadata.dart b/lib/dashboard/drawer/ssi/verifiers_metadata/verifiers_metadata.dart new file mode 100644 index 000000000..643c54be7 --- /dev/null +++ b/lib/dashboard/drawer/ssi/verifiers_metadata/verifiers_metadata.dart @@ -0,0 +1 @@ +export 'view/verifiers_metadata_page.dart'; diff --git a/lib/dashboard/drawer/ssi/verifiers_metadata/view/verifiers_metadata_page.dart b/lib/dashboard/drawer/ssi/verifiers_metadata/view/verifiers_metadata_page.dart new file mode 100644 index 000000000..181a512cb --- /dev/null +++ b/lib/dashboard/drawer/ssi/verifiers_metadata/view/verifiers_metadata_page.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +import 'package:altme/app/app.dart'; +import 'package:altme/dashboard/dashboard.dart'; +import 'package:dio/dio.dart'; + +import 'package:flutter/material.dart'; +import 'package:secure_storage/secure_storage.dart'; + +class VerifiersMetadataPage extends StatelessWidget { + const VerifiersMetadataPage({super.key}); + + static Route route() => MaterialPageRoute( + builder: (_) => const VerifiersMetadataPage(), + settings: const RouteSettings(name: '/VerifiersMetadataPage'), + ); + + @override + Widget build(BuildContext context) { + return const VerifiersMetadataView(); + } +} + +class VerifiersMetadataView extends StatelessWidget { + const VerifiersMetadataView({super.key}); + + Future getData() async { + try { + final response = await DioClient( + secureStorageProvider: getSecureStorage, + dio: Dio(), + ).get(Parameters.walletMetadataForVerifier); + final data = response is String + ? jsonDecode(response) as Map + : response as Map; + final value = const JsonEncoder.withIndent(' ').convert(data); + return value; + } catch (e) { + return ''; + } + } + + @override + Widget build(BuildContext context) { + return BasePage( + title: 'Wallet metadata for verifiers', + titleAlignment: Alignment.topCenter, + titleLeading: const BackLeadingButton(), + padding: const EdgeInsets.only( + top: 0, + bottom: Sizes.spaceSmall, + left: Sizes.spaceSmall, + right: Sizes.spaceSmall, + ), + secureScreen: true, + body: FutureBuilder( + future: getData(), + builder: (context, snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + return JsonViewWidget(data: snapshot.data.toString()); + + case ConnectionState.waiting: + case ConnectionState.none: + case ConnectionState.active: + return const Center(child: CircularProgressIndicator()); + } + }, + ), + ); + } +} diff --git a/lib/dashboard/json_viewer/json_viewer.dart b/lib/dashboard/json_viewer/json_viewer.dart index c590b3b38..5398c177b 100644 --- a/lib/dashboard/json_viewer/json_viewer.dart +++ b/lib/dashboard/json_viewer/json_viewer.dart @@ -1 +1,2 @@ export 'view/json_viewer_page.dart'; +export 'widget/json_viewer_widget.dart'; diff --git a/lib/dashboard/json_viewer/view/json_viewer_page.dart b/lib/dashboard/json_viewer/view/json_viewer_page.dart index 0592ce10d..99c5099c5 100644 --- a/lib/dashboard/json_viewer/view/json_viewer_page.dart +++ b/lib/dashboard/json_viewer/view/json_viewer_page.dart @@ -1,4 +1,5 @@ import 'package:altme/app/app.dart'; +import 'package:altme/dashboard/dashboard.dart'; import 'package:flutter/material.dart'; class JsonViewerPage extends StatelessWidget { @@ -44,52 +45,13 @@ class JsonViewerView extends StatelessWidget { @override Widget build(BuildContext context) { - final pattern = RegExp(r'(.*?)<\/b>'); - final matches = pattern.allMatches(data); - - final textSpans = []; - int currentIndex = 0; - - for (final match in matches) { - final plainText = data.substring(currentIndex, match.start); - final boldText = data.substring(match.start + 3, match.end - 4); - textSpans.add( - TextSpan( - text: plainText, - style: Theme.of(context).textTheme.bodyMedium, - ), - ); - textSpans.add( - TextSpan( - text: boldText, - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(fontWeight: FontWeight.w700), - ), - ); - currentIndex = match.end; - } - - if (currentIndex < data.length) { - final remainingText = data.substring(currentIndex); - textSpans.add( - TextSpan( - text: remainingText, - style: Theme.of(context).textTheme.bodyMedium, - ), - ); - } - return BasePage( title: title, titleAlignment: Alignment.topCenter, scrollView: true, titleLeading: const BackLeadingButton(), padding: const EdgeInsets.symmetric(horizontal: 10), - body: RichText( - text: TextSpan(children: textSpans), - ), + body: JsonViewWidget(data: data), ); } } diff --git a/lib/dashboard/json_viewer/widget/json_viewer_widget.dart b/lib/dashboard/json_viewer/widget/json_viewer_widget.dart new file mode 100644 index 000000000..6b2325dc3 --- /dev/null +++ b/lib/dashboard/json_viewer/widget/json_viewer_widget.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +class JsonViewWidget extends StatelessWidget { + const JsonViewWidget({super.key, required this.data}); + + final String data; + + @override + Widget build(BuildContext context) { + final pattern = RegExp(r'(.*?)<\/b>'); + final matches = pattern.allMatches(data); + + final textSpans = []; + int currentIndex = 0; + + for (final match in matches) { + final plainText = data.substring(currentIndex, match.start); + final boldText = data.substring(match.start + 3, match.end - 4); + textSpans.add( + TextSpan( + text: plainText, + style: Theme.of(context).textTheme.bodyMedium, + ), + ); + textSpans.add( + TextSpan( + text: boldText, + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(fontWeight: FontWeight.w700), + ), + ); + currentIndex = match.end; + } + + if (currentIndex < data.length) { + final remainingText = data.substring(currentIndex); + textSpans.add( + TextSpan( + text: remainingText, + style: Theme.of(context).textTheme.bodyMedium, + ), + ); + } + + return RichText(text: TextSpan(children: textSpans)); + } +} diff --git a/lib/dashboard/json_viewer/widget/widget.dart b/lib/dashboard/json_viewer/widget/widget.dart new file mode 100644 index 000000000..d97a8e946 --- /dev/null +++ b/lib/dashboard/json_viewer/widget/widget.dart @@ -0,0 +1 @@ +export 'json_viewer_widget.dart'; From c912e99b08491a8f80e4dbaed8796f76320fb856 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 14:54:50 +0545 Subject: [PATCH 04/23] refactor: Update token request and use only pincode or txcode #3029 --- .../view/oid4c4vc_credential_pick_page.dart | 8 ++++++++ .../cubit/qr_code_scan_cubit.dart | 19 ++++++++++++++++++- .../initiate_oidv4vc_credential_issuance.dart | 5 +++++ packages/oidc4vc/lib/src/oidc4vc.dart | 11 ++++++++--- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart index fff935853..cdf495ae7 100644 --- a/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart @@ -11,6 +11,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { super.key, required this.credentials, required this.userPin, + required this.txCode, required this.preAuthorizedCode, required this.issuer, required this.isEBSI, @@ -20,6 +21,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { final List credentials; final String? userPin; + final String? txCode; final String? preAuthorizedCode; final String issuer; final bool isEBSI; @@ -29,6 +31,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { static Route route({ required List credentials, required String? userPin, + required String? txCode, required String? preAuthorizedCode, required String issuer, required bool isEBSI, @@ -39,6 +42,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { builder: (context) => Oidc4vcCredentialPickPage( credentials: credentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, @@ -55,6 +59,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { child: Oidc4vcCredentialPickView( credentials: credentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, @@ -70,6 +75,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { super.key, required this.credentials, required this.userPin, + required this.txCode, required this.preAuthorizedCode, required this.issuer, required this.isEBSI, @@ -79,6 +85,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { final List credentials; final String? userPin; + final String? txCode; final String? preAuthorizedCode; final String issuer; final bool isEBSI; @@ -203,6 +210,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { .processSelectedCredentials( selectedCredentials: selectedCredentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index b89b838ae..5f3a8d2a7 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -523,7 +523,15 @@ class QRCodeScanCubit extends Cubit { onCancel: () { goBack(); }, - onProceed: (String userPin) async { + onProceed: (String pinCode) async { + String? userPin; + String? txCodeData; + + if (txCode != null) { + txCodeData = pinCode; + } else { + userPin = pinCode; + } await initiateOIDC4VCCredentialIssuance( scannedResponse: scannedResponse, credentialsCubit: credentialsCubit, @@ -532,6 +540,7 @@ class QRCodeScanCubit extends Cubit { secureStorageProvider: getSecureStorage, dioClient: client, userPin: userPin, + txCode: txCodeData, oidc4vc: oidc4vc, isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, @@ -561,6 +570,7 @@ class QRCodeScanCubit extends Cubit { secureStorageProvider: getSecureStorage, dioClient: client, userPin: null, + txCode: null, credentialOfferJson: credentialOfferJson, isEBSI: isEBSI, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, @@ -891,6 +901,7 @@ class QRCodeScanCubit extends Cubit { void navigateToOidc4vcCredentialPickPage({ required List credentials, required String? userPin, + required String? txCode, required String? preAuthorizedCode, required String issuer, required bool isEBSI, @@ -903,6 +914,7 @@ class QRCodeScanCubit extends Cubit { route: Oidc4vcCredentialPickPage.route( credentials: credentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, @@ -1260,6 +1272,7 @@ class QRCodeScanCubit extends Cubit { required List selectedCredentials, required bool isEBSI, required String? userPin, + required String? txCode, required String? preAuthorizedCode, required String issuer, required dynamic credentialOfferJson, @@ -1286,6 +1299,7 @@ class QRCodeScanCubit extends Cubit { selectedCredentials: selectedCredentials, isEBSI: isEBSI, userPin: userPin, + txCode: txCode, preAuthorizedCode: preAuthorizedCode, issuer: issuer, codeForAuthorisedFlow: null, @@ -1340,6 +1354,7 @@ class QRCodeScanCubit extends Cubit { required List selectedCredentials, required bool isEBSI, required String? userPin, + required String? txCode, required String? preAuthorizedCode, required String issuer, required String? codeForAuthorisedFlow, @@ -1389,6 +1404,7 @@ class QRCodeScanCubit extends Cubit { clientId: clientId, clientSecret: clientSecret, userPin: userPin, + txCode: txCode, code: codeForAuthorisedFlow, codeVerifier: codeVerifier, authorization: authorization, @@ -1596,6 +1612,7 @@ class QRCodeScanCubit extends Cubit { await addCredentialsInLoop( selectedCredentials: selectedCredentials, userPin: null, + txCode: null, issuer: issuer, preAuthorizedCode: null, isEBSI: isEBSI, diff --git a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart index 724703770..e393ed419 100644 --- a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart +++ b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart @@ -20,6 +20,7 @@ Future initiateOIDC4VCCredentialIssuance({ required SecureStorageProvider secureStorageProvider, required DioClient dioClient, required String? userPin, + required String? txCode, required dynamic credentialOfferJson, required bool cryptoHolderBinding, required OpenIdConfiguration? openIdConfiguration, @@ -86,6 +87,7 @@ Future initiateOIDC4VCCredentialIssuance({ qrCodeScanCubit.navigateToOidc4vcCredentialPickPage( credentials: credentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, @@ -98,6 +100,7 @@ Future initiateOIDC4VCCredentialIssuance({ qrCodeScanCubit.navigateToOidc4vcCredentialPickPage( credentials: credentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, @@ -129,6 +132,7 @@ Future initiateOIDC4VCCredentialIssuance({ await qrCodeScanCubit.addCredentialsInLoop( selectedCredentials: selectedCredentials, userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: null, isEBSI: isEBSI, @@ -147,6 +151,7 @@ Future initiateOIDC4VCCredentialIssuance({ // full phase flow of preAuthorized await qrCodeScanCubit.processSelectedCredentials( userPin: userPin, + txCode: txCode, issuer: issuer, preAuthorizedCode: preAuthorizedCode, isEBSI: isEBSI, diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index 7a8856f4f..c2958b247 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -588,8 +588,9 @@ class OIDC4VC { required OpenIdConfiguration openIdConfiguration, required Dio dio, required bool useOAuthAuthorizationServerLink, + required String? userPin, + required String? txCode, String? preAuthorizedCode, - String? userPin, String? code, String? codeVerifier, String? authorization, @@ -615,6 +616,7 @@ class OIDC4VC { code: code, codeVerifier: codeVerifier, clientId: clientId, + txCode: txCode, clientSecret: clientSecret, authorization: authorization, redirectUri: redirectUri, @@ -771,6 +773,7 @@ class OIDC4VC { required String redirectUri, String? preAuthorizedCode, String? userPin, + String? txCode, String? code, String? codeVerifier, String? clientId, @@ -808,9 +811,11 @@ class OIDC4VC { if (userPin != null) { tokenData['user_pin'] = userPin; + } - /// draft 13 - tokenData['tx_code'] = userPin; + /// draft 13 and above + if (txCode != null) { + tokenData['tx_code'] = txCode; } return tokenData; From 694dbe735d6ec0dce7d2c72fdfedb24802698ffb Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 15:52:29 +0545 Subject: [PATCH 05/23] feat: Set default value for pin code length and description #3030 --- lib/dashboard/user_pin/view/user_pin_page.dart | 5 ++--- lib/l10n/arb/app_ca.arb | 1 - lib/l10n/arb/app_en.arb | 4 ++-- lib/l10n/arb/app_es.arb | 3 +-- lib/l10n/arb/app_fr.arb | 1 - lib/l10n/untranslated.json | 9 ++++++--- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/dashboard/user_pin/view/user_pin_page.dart b/lib/dashboard/user_pin/view/user_pin_page.dart index 20a311984..f56b3defa 100644 --- a/lib/dashboard/user_pin/view/user_pin_page.dart +++ b/lib/dashboard/user_pin/view/user_pin_page.dart @@ -88,9 +88,8 @@ class _UserPinViewState extends State { backgroundColor: Theme.of(context).colorScheme.surface, scrollView: false, body: PinCodeWidget( - title: widget.txCode?.description ?? - l10n.pleaseInsertTheSecredCodeReceived, - passwordDigits: widget.txCode?.length ?? 4, + title: widget.txCode?.description ?? l10n.enterYourSecretCode, + passwordDigits: widget.txCode?.length ?? 6, deleteButton: Text( l10n.delete, style: Theme.of(context).textTheme.labelLarge, diff --git a/lib/l10n/arb/app_ca.arb b/lib/l10n/arb/app_ca.arb index 60dbc2674..108e25eb5 100644 --- a/lib/l10n/arb/app_ca.arb +++ b/lib/l10n/arb/app_ca.arb @@ -897,7 +897,6 @@ "pleaseSwitchToCorrectOIDC4VCProfile": "Canvia al perfil OIDC4VC correcte.", "authenticationSuccess": "Autenticació correcta", "format": "Format", - "pleaseInsertTheSecredCodeReceived": "Escriu el codi secret que has rebut.", "verifyIssuerWebsiteIdentity": "Verificar la identitat del lloc web de l'emissor", "verifyIssuerWebsiteIdentitySubtitle": "Per defecte: desactivat\nActivar per verificar la identitat del lloc web abans de l’accés.", "developerMode": "Mode desenvolupador", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 9e2142775..2f7640f93 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -894,7 +894,6 @@ "pleaseSwitchToCorrectOIDC4VCProfile": "Please switch to correct OIDC4VC profile.", "authenticationSuccess": "Authentication Success", "format": "Format", - "pleaseInsertTheSecredCodeReceived": "Please insert the secret code received.", "verifyIssuerWebsiteIdentity": "Verify issuer website identity", "verifyIssuerWebsiteIdentitySubtitle": "Enable to verify website identity before access. Default: Off.", "developerMode": "Developer Mode", @@ -1154,5 +1153,6 @@ }, "credentialPickShare": "Share", "credentialPickTitle": "Choose the credential(s) to wish to obtain", - "credentialShareTitle": "Choose the credential(s) to share" + "credentialShareTitle": "Choose the credential(s) to share", + "enterYourSecretCode": "Enter your secret code." } diff --git a/lib/l10n/arb/app_es.arb b/lib/l10n/arb/app_es.arb index 726b69bc5..0e72db31c 100644 --- a/lib/l10n/arb/app_es.arb +++ b/lib/l10n/arb/app_es.arb @@ -896,8 +896,7 @@ "oidc4vcProfile": "Perfil de OIDC4VC", "pleaseSwitchToCorrectOIDC4VCProfile": "Cambie al perfil de OIDC4VC correcto.", "authenticationSuccess": "Autenticación correcta", - "format": "Formato", - "pleaseInsertTheSecredCodeReceived": "Inserte el código secreto recibido.", + "format": "Formato", "verifyIssuerWebsiteIdentity": "Verificar la identidad del sitio web del emisor", "verifyIssuerWebsiteIdentitySubtitle": "Predeterminado: Desactivado\nActívelo para verificar la identidad del sitio web antes de acceder.", "developerMode": "Modo de desarrollador", diff --git a/lib/l10n/arb/app_fr.arb b/lib/l10n/arb/app_fr.arb index 6cabd8fb0..7dd2eb58a 100644 --- a/lib/l10n/arb/app_fr.arb +++ b/lib/l10n/arb/app_fr.arb @@ -897,7 +897,6 @@ "pleaseSwitchToCorrectOIDC4VCProfile": "Veuillez passer au bon profil OIDC4VC.", "authenticationSuccess": "Authentification Réussie", "format": "Format", - "pleaseInsertTheSecredCodeReceived": "Veuillez insérer le code secret reçu.", "verifyIssuerWebsiteIdentity": "Vérifier l'identité du site Web de l'émetteur", "verifyIssuerWebsiteIdentitySubtitle": "Par défaut : Désactivé\nActivez pour vérifier l'identité du site Web avant l'accès.", "developerMode": "Mode Développeur", diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 9990f4f69..038d87224 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -70,7 +70,8 @@ "restoreAnAppBackup", "credentialPickShare", "credentialPickTitle", - "credentialShareTitle" + "credentialShareTitle", + "enterYourSecretCode" ], "es": [ @@ -144,7 +145,8 @@ "restoreAnAppBackup", "credentialPickShare", "credentialPickTitle", - "credentialShareTitle" + "credentialShareTitle", + "enterYourSecretCode" ], "fr": [ @@ -223,6 +225,7 @@ "restoreAnAppBackup", "credentialPickShare", "credentialPickTitle", - "credentialShareTitle" + "credentialShareTitle", + "enterYourSecretCode" ] } From 5afb380eca864f09187a042f467d5346ad0b9396 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Mon, 4 Nov 2024 16:24:39 +0545 Subject: [PATCH 06/23] feat: Show activity log by default #2993 --- lib/dashboard/profile/models/profile_setting.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index 873558454..70b046d05 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -816,7 +816,7 @@ class SettingsMenu extends Equatable { required this.displayHelpCenter, required this.displayProfile, this.displaySelfSovereignIdentity = true, - this.displayActivityLog = false, + this.displayActivityLog = true, }); factory SettingsMenu.fromJson(Map json) => From bc3ceb75af5f8aaddaecfbb8c392fe7486251e73 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 10:35:56 +0545 Subject: [PATCH 07/23] fix: Update decentralised Id page #3055 --- .../jwk_thumbprint_p256_key_page.dart | 2 +- lib/l10n/arb/app_en.arb | 7 ++++--- lib/l10n/untranslated.json | 9 ++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/dashboard/drawer/ssi/manage_did/view/jwk_thumbprint_p256_key/jwk_thumbprint_p256_key_page.dart b/lib/dashboard/drawer/ssi/manage_did/view/jwk_thumbprint_p256_key/jwk_thumbprint_p256_key_page.dart index bfa876809..c604947a4 100644 --- a/lib/dashboard/drawer/ssi/manage_did/view/jwk_thumbprint_p256_key/jwk_thumbprint_p256_key_page.dart +++ b/lib/dashboard/drawer/ssi/manage_did/view/jwk_thumbprint_p256_key/jwk_thumbprint_p256_key_page.dart @@ -77,7 +77,7 @@ class _JWKThumbprintP256KeyPageState extends State mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - l10n.did, + l10n.jwk, style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox( diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 2f7640f93..517215048 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -934,7 +934,7 @@ "theCredentialOfferIsInvalid": "The credential offer is invalid", "dateOfRequest": "Date of Request", "keyDecentralizedIDP256": "did:key P-256", - "jwkDecentralizedIDP256": "JWK Thumbprint P-256", + "jwkDecentralizedIDP256": "did:jwk P-256", "defaultDid": "Default DID", "selectOneOfTheDid": "Select one of the DIDs", "theServiceIsNotAvailable": "The service is not available", @@ -1006,7 +1006,7 @@ "statusList": "Status list", "statusListIndex": "Status list index", "theWalletIsSuspended": "The wallet is suspended.", - "jwkThumbprintP256Key": "did:jwk P-256", + "jwkThumbprintP256Key": "JWK Thumbprint P-256", "walletBlockedPopupTitle": "Blockerd 10 minutes", "walletBlockedPopupDescription": "Too many failed attempts, your wallet is blocked for your security.\nYou can reset your wallet in order to use servives again.", "deleteMyWalletForWrontPincodeTitle": "Account blocked after 3 unsuccessful attempts", @@ -1154,5 +1154,6 @@ "credentialPickShare": "Share", "credentialPickTitle": "Choose the credential(s) to wish to obtain", "credentialShareTitle": "Choose the credential(s) to share", - "enterYourSecretCode": "Enter your secret code." + "enterYourSecretCode": "Enter your secret code.", + "jwk": "JWK" } diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 038d87224..85fe11a97 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -71,7 +71,8 @@ "credentialPickShare", "credentialPickTitle", "credentialShareTitle", - "enterYourSecretCode" + "enterYourSecretCode", + "jwk" ], "es": [ @@ -146,7 +147,8 @@ "credentialPickShare", "credentialPickTitle", "credentialShareTitle", - "enterYourSecretCode" + "enterYourSecretCode", + "jwk" ], "fr": [ @@ -226,6 +228,7 @@ "credentialPickShare", "credentialPickTitle", "credentialShareTitle", - "enterYourSecretCode" + "enterYourSecretCode", + "jwk" ] } From 49a0c485aaa4d42a13ae39cf24e7a4dbd3a677cb Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 10:43:01 +0545 Subject: [PATCH 08/23] version update: 2.16.4+539 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index bc13c8f17..322281a70 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.16.3+538 +version: 2.16.4+539 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: From 31286585c1ad65085487b7cc4735ec83bc037304 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 11:15:12 +0545 Subject: [PATCH 09/23] refactore: Update profilesetting.g.dart --- lib/dashboard/profile/models/profile_setting.g.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dashboard/profile/models/profile_setting.g.dart b/lib/dashboard/profile/models/profile_setting.g.dart index 3e380370d..f336c9145 100644 --- a/lib/dashboard/profile/models/profile_setting.g.dart +++ b/lib/dashboard/profile/models/profile_setting.g.dart @@ -333,7 +333,7 @@ SettingsMenu _$SettingsMenuFromJson(Map json) => SettingsMenu( displayProfile: json['displayProfile'] as bool, displaySelfSovereignIdentity: json['displaySelfSovereignIdentity'] as bool? ?? true, - displayActivityLog: json['displayActivityLog'] as bool? ?? false, + displayActivityLog: json['displayActivityLog'] as bool? ?? true, ); Map _$SettingsMenuToJson(SettingsMenu instance) => From 81ec55cc3976104e1b7e2b018b869f72a0edf58d Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 12:01:40 +0545 Subject: [PATCH 10/23] feat: Cusomise PIN code title based on situation #2977 --- .../verify_age/view/ai_age_result_page.dart | 2 ++ .../verify_age/view/verify_age_page.dart | 1 + .../widgets/manage_accounts_item.dart | 1 + .../reset_wallet/view/reset_wallet_menu.dart | 1 + .../ssi/manage_did/widgets/did_private_key.dart | 1 + .../helper_function/security_check.dart | 2 ++ .../src/view/wallet_security_menu.dart | 3 +++ .../view/polygon_id_credential_offer_view.dart | 1 + .../view/polygon_id_verification_view.dart | 1 + ...ntial_manifest_credential_offer_pick_page.dart | 1 + .../query_by_example_credentials_pick_page.dart | 2 ++ .../view/selective_disclosure_pick_page.dart | 1 + .../view/confirm_token_transaction_page.dart | 1 + lib/dashboard/src/view/dashboard_page.dart | 1 + lib/l10n/arb/app_en.arb | 5 ++++- lib/l10n/untranslated.json | 15 ++++++++++++--- lib/pin_code/view/pin_code_page.dart | 10 ++++++++-- lib/splash/bloclisteners/blocklisteners.dart | 3 +++ test/pin_code/view/pin_code_page_test.dart | 2 ++ 19 files changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/dashboard/ai_age_verification/verify_age/view/ai_age_result_page.dart b/lib/dashboard/ai_age_verification/verify_age/view/ai_age_result_page.dart index 860bed6a2..176a1c37e 100644 --- a/lib/dashboard/ai_age_verification/verify_age/view/ai_age_result_page.dart +++ b/lib/dashboard/ai_age_verification/verify_age/view/ai_age_result_page.dart @@ -204,6 +204,7 @@ class FailureWidget extends StatelessWidget { onPressed: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.pushReplacement( @@ -226,6 +227,7 @@ class FailureWidget extends StatelessWidget { onPressed: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { context diff --git a/lib/dashboard/ai_age_verification/verify_age/view/verify_age_page.dart b/lib/dashboard/ai_age_verification/verify_age/view/verify_age_page.dart index f01bc8f59..24eb219e3 100644 --- a/lib/dashboard/ai_age_verification/verify_age/view/verify_age_page.dart +++ b/lib/dashboard/ai_age_verification/verify_age/view/verify_age_page.dart @@ -81,6 +81,7 @@ class _VerifyAgeViewState extends State { onPressed: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.push( diff --git a/lib/dashboard/drawer/blockchain_settings/manage_accounts/widgets/manage_accounts_item.dart b/lib/dashboard/drawer/blockchain_settings/manage_accounts/widgets/manage_accounts_item.dart index e241ae134..82cfcaea9 100644 --- a/lib/dashboard/drawer/blockchain_settings/manage_accounts/widgets/manage_accounts_item.dart +++ b/lib/dashboard/drawer/blockchain_settings/manage_accounts/widgets/manage_accounts_item.dart @@ -139,6 +139,7 @@ class ManageAccountsItem extends StatelessWidget { if (confirm) { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.of(context).push( diff --git a/lib/dashboard/drawer/reset_wallet/view/reset_wallet_menu.dart b/lib/dashboard/drawer/reset_wallet/view/reset_wallet_menu.dart index ea99fee3d..3531b0f7a 100644 --- a/lib/dashboard/drawer/reset_wallet/view/reset_wallet_menu.dart +++ b/lib/dashboard/drawer/reset_wallet/view/reset_wallet_menu.dart @@ -101,6 +101,7 @@ class ResetWalletView extends StatelessWidget { ? () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () async { await resetWallet(context); diff --git a/lib/dashboard/drawer/ssi/manage_did/widgets/did_private_key.dart b/lib/dashboard/drawer/ssi/manage_did/widgets/did_private_key.dart index 2a158807c..175a3b355 100644 --- a/lib/dashboard/drawer/ssi/manage_did/widgets/did_private_key.dart +++ b/lib/dashboard/drawer/ssi/manage_did/widgets/did_private_key.dart @@ -51,6 +51,7 @@ class DidPrivateKey extends StatelessWidget { if (confirm) { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.push(context, route); diff --git a/lib/dashboard/drawer/wallet_security/helper_function/security_check.dart b/lib/dashboard/drawer/wallet_security/helper_function/security_check.dart index 0e6881be0..83da8c3ac 100644 --- a/lib/dashboard/drawer/wallet_security/helper_function/security_check.dart +++ b/lib/dashboard/drawer/wallet_security/helper_function/security_check.dart @@ -7,6 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; Future securityCheck({ required BuildContext context, + required String title, required VoidCallback onSuccess, required LocalAuthApi localAuthApi, }) async { @@ -19,6 +20,7 @@ Future securityCheck({ case WalletProtectionType.FA2: await Navigator.of(context).push( PinCodePage.route( + title: title, isValidCallback: onSuccess.call, restrictToBack: false, walletProtectionType: walletProtectionType, diff --git a/lib/dashboard/drawer/wallet_security/src/view/wallet_security_menu.dart b/lib/dashboard/drawer/wallet_security/src/view/wallet_security_menu.dart index 1fa8698cb..7049abbb8 100644 --- a/lib/dashboard/drawer/wallet_security/src/view/wallet_security_menu.dart +++ b/lib/dashboard/drawer/wallet_security/src/view/wallet_security_menu.dart @@ -50,6 +50,7 @@ class WalletSecurityView extends StatelessWidget { onTap: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.of(context) @@ -78,6 +79,7 @@ class WalletSecurityView extends StatelessWidget { if (confirm) { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.of(context) @@ -102,6 +104,7 @@ class WalletSecurityView extends StatelessWidget { onTap: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.of(context).push( diff --git a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart index eb56b2380..2943e0004 100644 --- a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart +++ b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart @@ -144,6 +144,7 @@ class PolygonIdCredentialOfferPage extends StatelessWidget { onPressed: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { context.read().addPolygonIdCredentials( diff --git a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_verification/view/polygon_id_verification_view.dart b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_verification/view/polygon_id_verification_view.dart index 7a5653fa3..055711afa 100644 --- a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_verification/view/polygon_id_verification_view.dart +++ b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_verification/view/polygon_id_verification_view.dart @@ -277,6 +277,7 @@ class _PolygonIdVerificationViewState extends State { ? () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { context diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart index 8c90f5466..bbb4dabce 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart @@ -349,6 +349,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { bool authenticated = false; await securityCheck( context: context, + title: context.l10n.typeYourPINCodeToShareTheData, localAuthApi: LocalAuthApi(), onSuccess: () { authenticated = true; diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/query_by_example/view/query_by_example_credentials_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/query_by_example/view/query_by_example_credentials_pick_page.dart index 46f967819..902cac23d 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/query_by_example/view/query_by_example_credentials_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/query_by_example/view/query_by_example_credentials_pick_page.dart @@ -178,6 +178,8 @@ class QueryByExampleCredentialPickView extends StatelessWidget { bool authenticated = false; await securityCheck( context: context, + title: context.l10n + .typeYourPINCodeToShareTheData, localAuthApi: LocalAuthApi(), onSuccess: () { authenticated = true; diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/selective_disclosure/view/selective_disclosure_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/selective_disclosure/view/selective_disclosure_pick_page.dart index 87a9fcf22..ed756175a 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/selective_disclosure/view/selective_disclosure_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/selective_disclosure/view/selective_disclosure_pick_page.dart @@ -209,6 +209,7 @@ class _SelectiveDisclosurePickViewState bool authenticated = false; await securityCheck( context: context, + title: context.l10n.typeYourPINCodeToShareTheData, localAuthApi: LocalAuthApi(), onSuccess: () { authenticated = true; diff --git a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart index 70e56657b..fd7953f10 100644 --- a/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart +++ b/lib/dashboard/home/tab_bar/tokens/confirm_token_transaction/view/confirm_token_transaction_page.dart @@ -266,6 +266,7 @@ class _ConfirmWithdrawalViewState extends State { ? () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { context diff --git a/lib/dashboard/src/view/dashboard_page.dart b/lib/dashboard/src/view/dashboard_page.dart index 09a1f8c5c..d36c45246 100644 --- a/lib/dashboard/src/view/dashboard_page.dart +++ b/lib/dashboard/src/view/dashboard_page.dart @@ -122,6 +122,7 @@ class _DashboardViewState extends State { onButtonClick: () async { await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () => Navigator.of(context) .push(RecoveryKeyPage.route()), diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 517215048..a3d4fa393 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -1155,5 +1155,8 @@ "credentialPickTitle": "Choose the credential(s) to wish to obtain", "credentialShareTitle": "Choose the credential(s) to share", "enterYourSecretCode": "Enter your secret code.", - "jwk": "JWK" + "jwk": "JWK", + "typeYourPINCodeToOpenTheWallet": "Type your PIN code to open the wallet", + "typeYourPINCodeToShareTheData": "Type your PIN code to share the data", + "typeYourPINCodeToAuthenticate": "Type your PIN code to authenticate" } diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 85fe11a97..26c87b9d2 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -72,7 +72,10 @@ "credentialPickTitle", "credentialShareTitle", "enterYourSecretCode", - "jwk" + "jwk", + "typeYourPINCodeToOpenTheWallet", + "typeYourPINCodeToShareTheData", + "typeYourPINCodeToAuthenticate" ], "es": [ @@ -148,7 +151,10 @@ "credentialPickTitle", "credentialShareTitle", "enterYourSecretCode", - "jwk" + "jwk", + "typeYourPINCodeToOpenTheWallet", + "typeYourPINCodeToShareTheData", + "typeYourPINCodeToAuthenticate" ], "fr": [ @@ -229,6 +235,9 @@ "credentialPickTitle", "credentialShareTitle", "enterYourSecretCode", - "jwk" + "jwk", + "typeYourPINCodeToOpenTheWallet", + "typeYourPINCodeToShareTheData", + "typeYourPINCodeToAuthenticate" ] } diff --git a/lib/pin_code/view/pin_code_page.dart b/lib/pin_code/view/pin_code_page.dart index da5007b91..c0b22aa37 100644 --- a/lib/pin_code/view/pin_code_page.dart +++ b/lib/pin_code/view/pin_code_page.dart @@ -8,24 +8,28 @@ import 'package:secure_storage/secure_storage.dart'; class PinCodePage extends StatelessWidget { const PinCodePage({ super.key, + required this.title, required this.isValidCallback, this.restrictToBack = true, required this.localAuthApi, required this.walletProtectionType, }); + final String title; final VoidCallback isValidCallback; final bool restrictToBack; final LocalAuthApi localAuthApi; final WalletProtectionType walletProtectionType; static Route route({ + required String title, required VoidCallback isValidCallback, required WalletProtectionType walletProtectionType, bool restrictToBack = true, }) => MaterialPageRoute( builder: (_) => PinCodePage( + title: title, isValidCallback: isValidCallback, restrictToBack: restrictToBack, localAuthApi: LocalAuthApi(), @@ -42,6 +46,7 @@ class PinCodePage extends StatelessWidget { secureStorageProvider: getSecureStorage, ), child: PinCodeView( + title: title, isValidCallback: isValidCallback, restrictToBack: restrictToBack, localAuthApi: localAuthApi, @@ -54,12 +59,14 @@ class PinCodePage extends StatelessWidget { class PinCodeView extends StatefulWidget { const PinCodeView({ super.key, + required this.title, required this.isValidCallback, this.restrictToBack = true, required this.localAuthApi, required this.walletProtectionType, }); + final String title; final VoidCallback isValidCallback; final bool restrictToBack; final LocalAuthApi localAuthApi; @@ -85,8 +92,7 @@ class _PinCodeViewState extends State { titleLeading: widget.restrictToBack ? null : const BackLeadingButton(), scrollView: false, body: PinCodeWidget( - title: l10n.enterYourPinCode, - subTitle: l10n.pinCodeMessage, + title: widget.title, deleteButton: Text( l10n.delete, style: Theme.of(context).textTheme.labelLarge, diff --git a/lib/splash/bloclisteners/blocklisteners.dart b/lib/splash/bloclisteners/blocklisteners.dart index f298aa74a..d1728d66f 100644 --- a/lib/splash/bloclisteners/blocklisteners.dart +++ b/lib/splash/bloclisteners/blocklisteners.dart @@ -32,6 +32,7 @@ final splashBlocListener = BlocListener( if (state.status == SplashStatus.routeToPassCode) { securityCheck( context: context, + title: context.l10n.typeYourPINCodeToOpenTheWallet, localAuthApi: LocalAuthApi(), onSuccess: () { Navigator.of(context).push(DashboardPage.route()); @@ -530,6 +531,7 @@ final qrCodeBlocListener = BlocListener( bool authenticated = false; await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { authenticated = true; @@ -844,6 +846,7 @@ final polygonIdBlocListener = BlocListener( await securityCheck( context: context, + title: l10n.typeYourPINCodeToAuthenticate, localAuthApi: LocalAuthApi(), onSuccess: () { context.read().authenticateOrGenerateProof( diff --git a/test/pin_code/view/pin_code_page_test.dart b/test/pin_code/view/pin_code_page_test.dart index 6319d6c05..a8115def2 100644 --- a/test/pin_code/view/pin_code_page_test.dart +++ b/test/pin_code/view/pin_code_page_test.dart @@ -70,6 +70,7 @@ void main() { Navigator.of(context).push( PinCodePage.route( isValidCallback: () {}, + title: '', walletProtectionType: WalletProtectionType.FA2, ), ); @@ -102,6 +103,7 @@ void main() { BlocProvider.value(value: flavorCubit), ], child: PinCodePage( + title: '', isValidCallback: () {}, walletProtectionType: WalletProtectionType.FA2, localAuthApi: localAuthApi, From 201b1a873a252bdfffe0764a2f282a6909e1b912 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 14:09:15 +0545 Subject: [PATCH 11/23] refactor: Choose first display if locale is not provided #3006 --- lib/app/shared/helper_functions/get_display.dart | 6 +++++- lib/app/shared/helper_functions/helper_functions.dart | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/app/shared/helper_functions/get_display.dart b/lib/app/shared/helper_functions/get_display.dart index 44600ad64..360e1dc6b 100644 --- a/lib/app/shared/helper_functions/get_display.dart +++ b/lib/app/shared/helper_functions/get_display.dart @@ -21,7 +21,11 @@ dynamic getDisplay(dynamic value, String languageCode) { orElse: () => displays.firstWhere( (element) => element is Map && element.containsKey('locale'), - orElse: () => null, + orElse: () => displays.firstWhere( + (element) => + element is Map, // if local is not provided + orElse: () => null, + ), ), ), ); diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index e37091348..460d09627 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -1755,7 +1755,8 @@ Future<(String?, String?, String?, String?, String?)> getClientDetails({ ) ?? credSupportedDisplay.firstWhereOrNull( (Display display) => display.locale != null, - ); + ) ?? + credSupportedDisplay.first; // if local is not provided } } } else if (openIdConfiguration.credentialConfigurationsSupported != null) { From af311096131915a542def838a04892dcf1359a60 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 16:45:55 +0545 Subject: [PATCH 12/23] feat: Add code for dpop support #3034 --- .../view/oidc4vc_settings_menu.dart | 1 + .../widget/dpop_support_widget.dart | 29 +++++++++++++++++++ .../ssi/oidc4vc_settngs/widget/widget.dart | 1 + .../profile/cubit/profile_cubit.dart | 2 ++ .../profile/models/profile_setting.dart | 5 ++++ .../profile/models/profile_setting.g.dart | 2 ++ 6 files changed, 40 insertions(+) create mode 100644 lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/dpop_support_widget.dart diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart index d3ab5f826..fc02edc3d 100644 --- a/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/view/oidc4vc_settings_menu.dart @@ -49,6 +49,7 @@ class Oidc4vcSettingMenuView extends StatelessWidget { const ProofHeaderWidget(), const PushAuthorizationRequesWidget(), const StatusListCachingWidget(), + //const DPopSupoprtWidget(), DrawerItem( title: 'Wallet metadata for issuers', onTap: () { diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/dpop_support_widget.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/dpop_support_widget.dart new file mode 100644 index 000000000..e378a3427 --- /dev/null +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/dpop_support_widget.dart @@ -0,0 +1,29 @@ +import 'package:altme/dashboard/dashboard.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class DPopSupoprtWidget extends StatelessWidget { + const DPopSupoprtWidget({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return OptionContainer( + title: 'Demonstrating Proof of Possession (DPoP)', + subtitle: 'Enable to protect code and access token.', + body: Switch( + onChanged: (value) async { + await context.read().updateProfileSetting( + dpopSupport: value, + ); + }, + value: state.model.profileSetting.selfSovereignIdentityOptions + .customOidc4vcProfile.dpopSupport, + activeColor: Theme.of(context).colorScheme.primary, + ), + ); + }, + ); + } +} diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/widget.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/widget.dart index fd70d3be3..fa5ad832f 100644 --- a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/widget.dart +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/widget.dart @@ -3,6 +3,7 @@ export 'client_type_widget.dart'; export 'confidential_client_widget.dart'; export 'cryptograhic_holder_binding.dart'; export 'did_key_type_widget.dart'; +export 'dpop_support_widget.dart'; export 'draft_type_widget.dart'; export 'option_container.dart'; export 'proof_header_widget.dart'; diff --git a/lib/dashboard/profile/cubit/profile_cubit.dart b/lib/dashboard/profile/cubit/profile_cubit.dart index d0452efe8..e332b1881 100644 --- a/lib/dashboard/profile/cubit/profile_cubit.dart +++ b/lib/dashboard/profile/cubit/profile_cubit.dart @@ -442,6 +442,7 @@ class ProfileCubit extends Cubit { bool? pushAuthorizationRequest, bool? statusListCaching, bool? displayNotification, + bool? dpopSupport, }) async { final profileModel = state.model.copyWith( profileSetting: state.model.profileSetting.copyWith( @@ -477,6 +478,7 @@ class ProfileCubit extends Cubit { proofType: proofType, pushAuthorizationRequest: pushAuthorizationRequest, statusListCache: statusListCaching, + dpopSupport: dpopSupport, ), ), ), diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index 70b046d05..c38ddcc8c 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -681,6 +681,7 @@ class CustomOidc4VcProfile extends Equatable { this.proofType = ProofType.jwt, this.pushAuthorizationRequest = false, this.statusListCache = true, + this.dpopSupport = false, }); factory CustomOidc4VcProfile.initial() => CustomOidc4VcProfile( @@ -728,6 +729,7 @@ class CustomOidc4VcProfile extends Equatable { @JsonKey(name: 'vcFormat') final VCFormatType vcFormatType; final ProofType proofType; + final bool dpopSupport; Map toJson() => _$CustomOidc4VcProfileToJson(this); @@ -764,6 +766,7 @@ class CustomOidc4VcProfile extends Equatable { ClientType? clientType, VCFormatType? vcFormatType, ProofType? proofType, + bool? dpopSupport, }) => CustomOidc4VcProfile( clientAuthentication: clientAuthentication ?? this.clientAuthentication, @@ -785,6 +788,7 @@ class CustomOidc4VcProfile extends Equatable { clientSecret: clientSecret ?? this.clientSecret, vcFormatType: vcFormatType ?? this.vcFormatType, proofType: proofType ?? this.proofType, + dpopSupport: dpopSupport ?? this.dpopSupport, ); @override @@ -806,6 +810,7 @@ class CustomOidc4VcProfile extends Equatable { clientType, vcFormatType, proofType, + dpopSupport, ]; } diff --git a/lib/dashboard/profile/models/profile_setting.g.dart b/lib/dashboard/profile/models/profile_setting.g.dart index f336c9145..e27b23f4a 100644 --- a/lib/dashboard/profile/models/profile_setting.g.dart +++ b/lib/dashboard/profile/models/profile_setting.g.dart @@ -242,6 +242,7 @@ CustomOidc4VcProfile _$CustomOidc4VcProfileFromJson( pushAuthorizationRequest: json['pushAuthorizationRequest'] as bool? ?? false, statusListCache: json['statusListCache'] as bool? ?? true, + dpopSupport: json['dpopSupport'] as bool? ?? false, ); Map _$CustomOidc4VcProfileToJson( @@ -265,6 +266,7 @@ Map _$CustomOidc4VcProfileToJson( 'subjectSyntaxeType': _$ClientTypeEnumMap[instance.clientType]!, 'vcFormat': _$VCFormatTypeEnumMap[instance.vcFormatType]!, 'proofType': _$ProofTypeEnumMap[instance.proofType]!, + 'dpopSupport': instance.dpopSupport, }; const _$ClientAuthenticationEnumMap = { From d9ce52d4a634e8d4bd260eddd55fa0c5cd630586 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Tue, 5 Nov 2024 19:33:22 +0545 Subject: [PATCH 13/23] fix: Add displayEmailPassSdJwt in copywith part #3046 --- lib/dashboard/profile/models/profile_setting.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index c38ddcc8c..20f5d2dd7 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -278,6 +278,7 @@ class DiscoverCardsOptions extends Equatable { bool? displayOver18Jwt, bool? displayVerifiableId, bool? displayVerifiableIdJwt, + bool? displayVerifiableIdSdJwt, bool? displayOver21, bool? displayOver65, bool? displayEmailPass, @@ -303,6 +304,8 @@ class DiscoverCardsOptions extends Equatable { displayVerifiableId: displayVerifiableId ?? this.displayVerifiableId, displayVerifiableIdJwt: displayVerifiableIdJwt ?? this.displayVerifiableIdJwt, + displayVerifiableIdSdJwt: + displayVerifiableIdSdJwt ?? this.displayVerifiableIdSdJwt, displayOver21: displayOver21 ?? this.displayOver21, displayOver65: displayOver65 ?? this.displayOver65, displayEmailPass: displayEmailPass ?? this.displayEmailPass, From 96a15730d4b0c8b11d846db2acf2e3ca3d083854 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Wed, 6 Nov 2024 12:15:37 +0545 Subject: [PATCH 14/23] feat: Bypass single credential selection for oidc4vp sd-jwt #2972 --- ...l_manifest_credential_offer_pick_page.dart | 99 +++++++++++++++---- 1 file changed, 80 insertions(+), 19 deletions(-) diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart index bbb4dabce..8971fbc19 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/view/credential_manifest_credential_offer_pick_page.dart @@ -73,7 +73,7 @@ class CredentialManifestOfferPickPage extends StatelessWidget { } } -class CredentialManifestOfferPickView extends StatelessWidget { +class CredentialManifestOfferPickView extends StatefulWidget { const CredentialManifestOfferPickView({ super.key, required this.uri, @@ -89,6 +89,66 @@ class CredentialManifestOfferPickView extends StatelessWidget { final int inputDescriptorIndex; final List credentialsToBePresented; + @override + State createState() => + _CredentialManifestOfferPickViewState(); +} + +class _CredentialManifestOfferPickViewState + extends State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + final isVcSdJWT = context + .read() + .state + .filteredCredentialList + .firstOrNull + ?.getFormat == + VCFormatType.vcSdJWT.vcValue; + + if (isVcSdJWT) { + final element = context + .read() + .state + .filteredCredentialList; + + final containsSingleElement = element.isNotEmpty && element.length == 1; + if (containsSingleElement) { + final PresentationDefinition? presentationDefinition = context + .read() + .state + .presentationDefinition; + + if (presentationDefinition != null) { + context.read().toggle( + index: 0, + inputDescriptor: presentationDefinition + .inputDescriptors[widget.inputDescriptorIndex], + isVcSdJWT: isVcSdJWT, + ); + + final credentialManifestState = + context.read().state; + final credentialToBePresented = credentialManifestState + .filteredCredentialList[credentialManifestState.selected.first]; + + Navigator.of(context).pushReplacement( + SelectiveDisclosurePickPage.route( + uri: widget.uri, + issuer: widget.issuer, + credential: widget.credential, + credentialToBePresented: credentialToBePresented, + presentationDefinition: presentationDefinition, + ), + ); + } + } + } + }); + } + @override Widget build(BuildContext context) { final l10n = context.l10n; @@ -140,7 +200,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { : Column( children: [ Text( - '${inputDescriptorIndex + 1}/${presentationDefinition.inputDescriptors.length}', + '${widget.inputDescriptorIndex + 1}/${presentationDefinition.inputDescriptors.length}', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 10), @@ -148,7 +208,8 @@ class CredentialManifestOfferPickView extends StatelessWidget { padding: const EdgeInsets.all(8), child: Text( presentationDefinition - .inputDescriptors[inputDescriptorIndex] + .inputDescriptors[ + widget.inputDescriptorIndex] .purpose ?? l10n.credentialPickSelect, style: Theme.of(context).textTheme.titleMedium, @@ -175,7 +236,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { inputDescriptor: presentationDefinition .inputDescriptors[ - inputDescriptorIndex], + widget.inputDescriptorIndex], isVcSdJWT: isVcSdJWT, ); }, @@ -207,9 +268,9 @@ class CredentialManifestOfferPickView extends StatelessWidget { Navigator.of(context) .pushReplacement( SelectiveDisclosurePickPage.route( - uri: uri, - issuer: issuer, - credential: credential, + uri: widget.uri, + issuer: widget.issuer, + credential: widget.credential, credentialToBePresented: credentialToBePresented, presentationDefinition: @@ -229,7 +290,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { final inputDescriptor = presentationDefinition! .inputDescriptors[ - inputDescriptorIndex]; + widget.inputDescriptorIndex]; final bool isOptional = inputDescriptor .constraints @@ -239,7 +300,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { false; final bool isOngoingStep = - inputDescriptorIndex + 1 != + widget.inputDescriptorIndex + 1 != presentationDefinition .inputDescriptors.length; @@ -306,7 +367,7 @@ class CredentialManifestOfferPickView extends StatelessWidget { late List updatedCredentials; if (skip) { updatedCredentials = List.of( - credentialsToBePresented, + widget.credentialsToBePresented, ); } else { final selectedCredentials = credentialManifestState.selected @@ -317,21 +378,21 @@ class CredentialManifestOfferPickView extends StatelessWidget { .toList(); updatedCredentials = List.of( - credentialsToBePresented, + widget.credentialsToBePresented, )..addAll(selectedCredentials); } getLogger('present') .i('credential to presented - ${updatedCredentials.length}'); - if (inputDescriptorIndex + 1 != + if (widget.inputDescriptorIndex + 1 != presentationDefinition.inputDescriptors.length) { await Navigator.of(context).pushReplacement( CredentialManifestOfferPickPage.route( - uri: uri, - credential: credential, - issuer: issuer, - inputDescriptorIndex: inputDescriptorIndex + 1, + uri: widget.uri, + credential: widget.credential, + issuer: widget.issuer, + inputDescriptorIndex: widget.inputDescriptorIndex + 1, credentialsToBePresented: updatedCredentials, ), ); @@ -361,11 +422,11 @@ class CredentialManifestOfferPickView extends StatelessWidget { } } await context.read().credentialOfferOrPresent( - uri: uri, - credentialModel: credential, + uri: widget.uri, + credentialModel: widget.credential, keyId: SecureStorageKeys.ssiKey, credentialsToBePresented: updatedCredentials, - issuer: issuer, + issuer: widget.issuer, qrCodeScanCubit: context.read(), ); } From 0b74940b682cccb2c713313dabed038f5f8a415e Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Wed, 6 Nov 2024 17:16:53 +0545 Subject: [PATCH 15/23] feat: Show token data and credential data to be sent #3054 --- .../shared/enum/status/qr_scan_status.dart | 1 + .../json_viewer/view/json_viewer_page.dart | 27 +- .../cubit/qr_code_scan_cubit.dart | 82 +++++-- .../cubit/qr_code_scan_cubit.g.dart | 1 + lib/oidc4vc/get_credential.dart | 173 +++++++++++-- lib/splash/bloclisteners/blocklisteners.dart | 23 ++ packages/oidc4vc/lib/src/oidc4vc.dart | 231 +----------------- packages/oidc4vc/test/src/oidc4vc_test.dart | 122 ++++----- 8 files changed, 341 insertions(+), 319 deletions(-) diff --git a/lib/app/shared/enum/status/qr_scan_status.dart b/lib/app/shared/enum/status/qr_scan_status.dart index 06d8365fa..c74986a3f 100644 --- a/lib/app/shared/enum/status/qr_scan_status.dart +++ b/lib/app/shared/enum/status/qr_scan_status.dart @@ -9,4 +9,5 @@ enum QrScanStatus { success, goBack, pauseForDialog, + pauseForDisplay, } diff --git a/lib/dashboard/json_viewer/view/json_viewer_page.dart b/lib/dashboard/json_viewer/view/json_viewer_page.dart index 99c5099c5..7c4a01d8d 100644 --- a/lib/dashboard/json_viewer/view/json_viewer_page.dart +++ b/lib/dashboard/json_viewer/view/json_viewer_page.dart @@ -1,5 +1,6 @@ import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; +import 'package:altme/l10n/l10n.dart'; import 'package:flutter/material.dart'; class JsonViewerPage extends StatelessWidget { @@ -7,19 +8,23 @@ class JsonViewerPage extends StatelessWidget { super.key, required this.title, required this.data, + required this.showContinueButton, }); final String title; final String data; + final bool showContinueButton; static Route route({ required String title, required String data, + bool showContinueButton = false, }) => MaterialPageRoute( builder: (_) => JsonViewerPage( title: title, data: data, + showContinueButton: showContinueButton, ), settings: const RouteSettings(name: '/JsonViewerPage'), ); @@ -29,6 +34,7 @@ class JsonViewerPage extends StatelessWidget { return JsonViewerView( title: title, data: data, + showContinueButton: showContinueButton, ); } } @@ -38,10 +44,12 @@ class JsonViewerView extends StatelessWidget { super.key, required this.title, required this.data, + required this.showContinueButton, }); final String title; final String data; + final bool showContinueButton; @override Widget build(BuildContext context) { @@ -49,9 +57,26 @@ class JsonViewerView extends StatelessWidget { title: title, titleAlignment: Alignment.topCenter, scrollView: true, - titleLeading: const BackLeadingButton(), + titleLeading: BackLeadingButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + ), padding: const EdgeInsets.symmetric(horizontal: 10), body: JsonViewWidget(data: data), + navigation: !showContinueButton + ? null + : Padding( + padding: const EdgeInsets.all( + Sizes.spaceSmall, + ), + child: MyElevatedButton( + text: context.l10n.continueString, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); } } diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 5f3a8d2a7..f1cc1ba14 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -1392,6 +1392,36 @@ class QRCodeScanCubit extends Cubit { ); if (savedAccessToken == null) { + /// get tokendata + final tokenData = oidc4vc.buildTokenData( + preAuthorizedCode: preAuthorizedCode, + userPin: userPin, + code: codeForAuthorisedFlow, + codeVerifier: codeVerifier, + clientId: clientId, + txCode: txCode, + clientSecret: clientSecret, + authorization: authorization, + redirectUri: Parameters.oidc4vcUniversalLink, + oAuthClientAttestation: oAuthClientAttestation, + oAuthClientAttestationPop: oAuthClientAttestationPop, + ); + + if (profileCubit.state.model.isDeveloperMode) { + final value = await showDataBeforeSending( + title: 'TOKEN DATA', + data: tokenData, + ); + if (value) { + completer = null; + } else { + completer = null; + resetNonceAndAccessTokenAndAuthorizationDetails(); + goBack(); + return; + } + } + /// get token response final ( Map? tokenResponse, @@ -1399,17 +1429,9 @@ class QRCodeScanCubit extends Cubit { String? cnonce, List? authorizationDetails, ) = await oidc4vc.getTokenResponse( - preAuthorizedCode: preAuthorizedCode, issuer: issuer, - clientId: clientId, - clientSecret: clientSecret, - userPin: userPin, - txCode: txCode, - code: codeForAuthorisedFlow, - codeVerifier: codeVerifier, authorization: authorization, oidc4vciDraftType: customOidc4vcProfile.oidc4vciDraft, - redirectUri: Parameters.oidc4vcUniversalLink, openIdConfiguration: OpenIdConfiguration.fromJson(openIdConfigurationData), oAuthClientAttestation: oAuthClientAttestation, @@ -1417,6 +1439,7 @@ class QRCodeScanCubit extends Cubit { dio: client.dio, useOAuthAuthorizationServerLink: useOauthServerAuthEndPoint(profileCubit.state.model), + tokenData: tokenData, ); savedAccessToken = accessToken; @@ -1458,11 +1481,7 @@ class QRCodeScanCubit extends Cubit { } /// get credentials - final ( - List encodedCredentialOrFutureTokens, - String? deferredCredentialEndpoint, - String format, - ) = await getCredential( + final result = await getCredential( isEBSI: isEBSI, credential: selectedCredentials[i], issuer: issuer, @@ -1472,13 +1491,22 @@ class QRCodeScanCubit extends Cubit { clientId: clientId, profileCubit: profileCubit, accessToken: savedAccessToken!, - nonce: savedNonce, + cnonce: savedNonce, authorizationDetails: savedAuthorizationDetails, openIdConfiguration: OpenIdConfiguration.fromJson(openIdConfigurationData), + qrCodeScanCubit: qrCodeScanCubit, ); - final lastElement = encodedCredentialOrFutureTokens.last; + if (result == null) return; + + final ( + encodedCredentialOrFutureTokens, + deferredCredentialEndpoint, + format + ) = result; + + final lastElement = encodedCredentialOrFutureTokens!.last; /// update nonce value if (lastElement is Map) { @@ -1525,7 +1553,7 @@ class QRCodeScanCubit extends Cubit { blockchainType: walletCubit.state.currentAccount!.blockchainType, deferredCredentialEndpoint: deferredCredentialEndpoint, encodedCredentialOrFutureTokens: encodedCredentialOrFutureTokens, - format: format, + format: format!, openIdConfiguration: OpenIdConfiguration.fromJson(openIdConfigurationData), qrCodeScanCubit: qrCodeScanCubit, @@ -1549,6 +1577,28 @@ class QRCodeScanCubit extends Cubit { } } + Future showDataBeforeSending({ + required String title, + required Map data, + }) async { + completer = Completer(); + + final formattedData = ''' +$title : +${const JsonEncoder.withIndent(' ').convert(data)}\n +'''; + emit( + state.copyWith( + qrScanStatus: QrScanStatus.pauseForDisplay, + dialogData: formattedData, + ), + ); + + final value = await completer!.future; + + return value; + } + void resetNonceAndAccessTokenAndAuthorizationDetails() { savedAccessToken = null; savedNonce = null; diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.g.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.g.dart index 99ff59198..61dfbd6ef 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.g.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.g.dart @@ -38,4 +38,5 @@ const _$QrScanStatusEnumMap = { QrScanStatus.success: 'success', QrScanStatus.goBack: 'goBack', QrScanStatus.pauseForDialog: 'pauseForDialog', + QrScanStatus.pauseForDisplay: 'pauseForDisplay', }; diff --git a/lib/oidc4vc/get_credential.dart b/lib/oidc4vc/get_credential.dart index 921577078..ae26bc588 100644 --- a/lib/oidc4vc/get_credential.dart +++ b/lib/oidc4vc/get_credential.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; import 'package:dio/dio.dart'; @@ -8,10 +10,10 @@ import 'package:oidc4vc/oidc4vc.dart'; // format Future< ( - List, + List?, + String?, String?, - String, - )> getCredential({ + )?> getCredential({ required bool isEBSI, required dynamic credential, required ProfileCubit profileCubit, @@ -21,9 +23,10 @@ Future< required DidKeyType didKeyType, required String? clientId, required String accessToken, - required String? nonce, + required String? cnonce, required OpenIdConfiguration openIdConfiguration, required List? authorizationDetails, + required QRCodeScanCubit qrCodeScanCubit, }) async { final privateKey = await fetchPrivateKey( isEBSI: isEBSI, @@ -41,33 +44,157 @@ Future< final customOidc4vcProfile = profileCubit.state.model.profileSetting .selfSovereignIdentityOptions.customOidc4vcProfile; - final ( - List encodedCredentialOrFutureTokens, - String? deferredCredentialEndpoint, - String format, - ) = await profileCubit.oidc4vc.getCredential( - issuer: issuer, + var nonce = cnonce; + + final (credentialType, types, credentialDefinition, vct, format) = + await profileCubit.oidc4vc.getCredentialData( + openIdConfiguration: openIdConfiguration, credential: credential, + ); + + final credentialResponseData = []; + + final issuerTokenParameters = IssuerTokenParameters( + privateKey: jsonDecode(privateKey) as Map, did: did, kid: kid, - clientId: clientId, - privateKey: privateKey, - cryptoHolderBinding: cryptoHolderBinding, - oidc4vciDraftType: oidc4vciDraftType, + issuer: issuer, + mediaType: MediaType.proofOfOwnership, clientType: customOidc4vcProfile.clientType, proofHeaderType: customOidc4vcProfile.proofHeader, - clientAuthentication: customOidc4vcProfile.clientAuthentication, - proofType: customOidc4vcProfile.proofType, - accessToken: accessToken, - cnonce: nonce, - authorizationDetails: authorizationDetails, - openIdConfiguration: openIdConfiguration, - dio: Dio(), - vcFormatType: customOidc4vcProfile.vcFormatType, + clientId: clientId ?? '', ); + if (authorizationDetails != null) { + final dynamic authDetailForCredential = authorizationDetails + .where( + (dynamic ele) => + ele is Map && + ((ele.containsKey('types') && + (ele['types'] as List).contains(credentialType)) || + (ele.containsKey('credential_definition') && + (ele['credential_definition']['type'] as List) + .contains(credentialType))), + ) + .firstOrNull; + + if (authDetailForCredential == null) { + throw Exception('AUTHORIZATION_DETAIL_ERROR'); + } + + final credentialIdentifiers = + (authDetailForCredential['credential_identifiers'] as List) + .map((dynamic element) => element.toString()) + .toList(); + + for (final credentialIdentifier in credentialIdentifiers) { + final credentialData = await profileCubit.oidc4vc.buildCredentialData( + nonce: nonce, + issuerTokenParameters: issuerTokenParameters, + openIdConfiguration: openIdConfiguration, + credentialType: credentialType, + types: types, + format: format, + credentialIdentifier: credentialIdentifier, + cryptoHolderBinding: cryptoHolderBinding, + oidc4vciDraftType: oidc4vciDraftType, + credentialDefinition: credentialDefinition, + clientAuthentication: customOidc4vcProfile.clientAuthentication, + vct: vct, + proofType: customOidc4vcProfile.proofType, + did: did, + issuer: issuer, + kid: kid, + privateKey: privateKey, + vcFormatType: customOidc4vcProfile.vcFormatType, + ); + + if (profileCubit.state.model.isDeveloperMode) { + final value = await qrCodeScanCubit.showDataBeforeSending( + title: 'CREDENTIAL DATA', + data: credentialData, + ); + + if (value) { + qrCodeScanCubit.completer = null; + } else { + qrCodeScanCubit.completer = null; + qrCodeScanCubit.resetNonceAndAccessTokenAndAuthorizationDetails(); + qrCodeScanCubit.goBack(); + return null; + } + } + + final credentialResponseDataValue = + await profileCubit.oidc4vc.getSingleCredential( + openIdConfiguration: openIdConfiguration, + accessToken: accessToken, + nonce: nonce, + dio: Dio(), + credentialData: credentialData, + ); + + /// update nonce value + if (credentialResponseDataValue is Map) { + if (credentialResponseDataValue.containsKey('c_nonce')) { + nonce = credentialResponseDataValue['c_nonce'].toString(); + } + } + + credentialResponseData.add(credentialResponseDataValue); + } + } else { + final credentialData = await profileCubit.oidc4vc.buildCredentialData( + nonce: nonce, + issuerTokenParameters: issuerTokenParameters, + openIdConfiguration: openIdConfiguration, + credentialType: credentialType, + types: types, + format: format, + credentialIdentifier: null, + cryptoHolderBinding: cryptoHolderBinding, + oidc4vciDraftType: oidc4vciDraftType, + credentialDefinition: credentialDefinition, + clientAuthentication: customOidc4vcProfile.clientAuthentication, + vct: vct, + proofType: customOidc4vcProfile.proofType, + did: did, + issuer: issuer, + kid: kid, + privateKey: privateKey, + vcFormatType: customOidc4vcProfile.vcFormatType, + ); + + if (profileCubit.state.model.isDeveloperMode) { + await qrCodeScanCubit.showDataBeforeSending( + title: 'CREDENTIAL DATA', + data: credentialData, + ); + + if (qrCodeScanCubit.savedAccessToken == null && + qrCodeScanCubit.savedNonce == null && + qrCodeScanCubit.savedAuthorizationDetails == null) { + return (null, null, null); + } + } + + final credentialResponseDataValue = + await profileCubit.oidc4vc.getSingleCredential( + openIdConfiguration: openIdConfiguration, + accessToken: accessToken, + nonce: cnonce, + dio: Dio(), + credentialData: credentialData, + ); + + credentialResponseData.add(credentialResponseDataValue); + } + + final deferredCredentialEndpoint = + profileCubit.oidc4vc.getDeferredCredentialEndpoint(openIdConfiguration); + return ( - encodedCredentialOrFutureTokens, + credentialResponseData, deferredCredentialEndpoint, format, ); diff --git a/lib/splash/bloclisteners/blocklisteners.dart b/lib/splash/bloclisteners/blocklisteners.dart index d1728d66f..28f9219cc 100644 --- a/lib/splash/bloclisteners/blocklisteners.dart +++ b/lib/splash/bloclisteners/blocklisteners.dart @@ -588,6 +588,29 @@ final qrCodeBlocListener = BlocListener( LoadingView().show(context: context); } + if (state.status == QrScanStatus.pauseForDisplay) { + LoadingView().hide(); + + final data = state.dialogData ?? ''; + + final returnedValue = await Navigator.of(context).push( + JsonViewerPage.route( + title: l10n.display, + data: data, + showContinueButton: true, + ), + ); + + var moveAhead = false; + + if (returnedValue != null && returnedValue is bool && returnedValue) { + moveAhead = true; + } + + context.read().completer?.complete(moveAhead); + LoadingView().show(context: context); + } + if (state.status == QrScanStatus.success) { if (state.route != null) { await Navigator.of(context).push(state.route!); diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index c2958b247..24a17219c 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -431,47 +431,10 @@ class OIDC4VC { }; } - /// Retreive credential_type from url - /// credentialResponseData, deferredCredentialEndpoint, format - - Future< - ( - List, - String?, - String, - )> getCredential({ - required String issuer, - required dynamic credential, - required String did, - required String? clientId, - required String kid, - required String privateKey, - required bool cryptoHolderBinding, - required ClientType clientType, - required ProofHeaderType proofHeaderType, - required OIDC4VCIDraftType oidc4vciDraftType, - required ClientAuthentication clientAuthentication, - required ProofType proofType, - required OpenIdConfiguration openIdConfiguration, - required String accessToken, - required String? cnonce, - required Dio dio, - required VCFormatType vcFormatType, - List? authorizationDetails, - }) async { - var nonce = cnonce; - - final issuerTokenParameters = IssuerTokenParameters( - privateKey: jsonDecode(privateKey) as Map, - did: did, - kid: kid, - issuer: issuer, - mediaType: MediaType.proofOfOwnership, - clientType: clientType, - proofHeaderType: proofHeaderType, - clientId: clientId ?? '', - ); - + ///deferredCredentialEndpoint + String? getDeferredCredentialEndpoint( + OpenIdConfiguration openIdConfiguration, + ) { String? deferredCredentialEndpoint; if (openIdConfiguration.deferredCredentialEndpoint != null) { @@ -479,124 +442,27 @@ class OIDC4VC { openIdConfiguration.deferredCredentialEndpoint; } - final (credentialType, types, credentialDefinition, vct, format) = - await getCredentialData( - openIdConfiguration: openIdConfiguration, - credential: credential, - ); - - final credentialResponseData = []; - - if (authorizationDetails != null) { - final dynamic authDetailForCredential = authorizationDetails - .where( - (dynamic ele) => - ele is Map && - ((ele.containsKey('types') && - (ele['types'] as List).contains(credentialType)) || - (ele.containsKey('credential_definition') && - (ele['credential_definition']['type'] as List) - .contains(credentialType))), - ) - .firstOrNull; - - if (authDetailForCredential == null) { - throw Exception('AUTHORIZATION_DETAIL_ERROR'); - } - - final credentialIdentifiers = - (authDetailForCredential['credential_identifiers'] as List) - .map((dynamic element) => element.toString()) - .toList(); - - for (final credentialIdentifier in credentialIdentifiers) { - final credentialResponseDataValue = await getSingleCredential( - issuerTokenParameters: issuerTokenParameters, - openIdConfiguration: openIdConfiguration, - credentialType: credentialType, - types: types, - format: format, - credentialIdentifier: credentialIdentifier, - cryptoHolderBinding: cryptoHolderBinding, - oidc4vciDraftType: oidc4vciDraftType, - credentialDefinition: credentialDefinition, - clientAuthentication: clientAuthentication, - vct: vct, - proofType: proofType, - did: did, - issuer: issuer, - kid: kid, - privateKey: privateKey, - accessToken: accessToken, - nonce: nonce, - dio: dio, - vcFormatType: vcFormatType, - ); - - /// update nonce value - if (credentialResponseDataValue is Map) { - if (credentialResponseDataValue.containsKey('c_nonce')) { - nonce = credentialResponseDataValue['c_nonce'].toString(); - } - } - - credentialResponseData.add(credentialResponseDataValue); - } -// - } else { - final credentialResponseDataValue = await getSingleCredential( - issuerTokenParameters: issuerTokenParameters, - openIdConfiguration: openIdConfiguration, - credentialType: credentialType, - types: types, - format: format, - cryptoHolderBinding: cryptoHolderBinding, - oidc4vciDraftType: oidc4vciDraftType, - credentialDefinition: credentialDefinition, - clientAuthentication: clientAuthentication, - vct: vct, - credentialIdentifier: null, - proofType: proofType, - did: did, - issuer: issuer, - kid: kid, - privateKey: privateKey, - accessToken: accessToken, - nonce: cnonce, - dio: dio, - vcFormatType: vcFormatType, - ); - - credentialResponseData.add(credentialResponseDataValue); - } - - return ( - credentialResponseData, - deferredCredentialEndpoint, - format, - ); + return deferredCredentialEndpoint; } /// tokenResponse, accessToken, cnonce, authorizationDetails Future<(Map?, String?, String?, List?)> getTokenResponse({ required String issuer, - required String? clientId, - required String? clientSecret, required OIDC4VCIDraftType oidc4vciDraftType, - required String redirectUri, required OpenIdConfiguration openIdConfiguration, required Dio dio, required bool useOAuthAuthorizationServerLink, - required String? userPin, - required String? txCode, - String? preAuthorizedCode, - String? code, - String? codeVerifier, + required Map tokenData, String? authorization, String? oAuthClientAttestation, String? oAuthClientAttestationPop, }) async { + Map? tokenResponse; + String? accessToken; + String? cnonce; + List? authorizationDetails; + final tokenEndPoint = await readTokenEndPoint( openIdConfiguration: openIdConfiguration, issuer: issuer, @@ -605,25 +471,6 @@ class OIDC4VC { useOAuthAuthorizationServerLink: useOAuthAuthorizationServerLink, ); - Map? tokenResponse; - String? accessToken; - String? cnonce; - List? authorizationDetails; - - final tokenData = buildTokenData( - preAuthorizedCode: preAuthorizedCode, - userPin: userPin, - code: code, - codeVerifier: codeVerifier, - clientId: clientId, - txCode: txCode, - clientSecret: clientSecret, - authorization: authorization, - redirectUri: redirectUri, - oAuthClientAttestation: oAuthClientAttestation, - oAuthClientAttestationPop: oAuthClientAttestationPop, - ); - tokenResponse = await getToken( tokenEndPoint: tokenEndPoint, tokenData: tokenData, @@ -647,51 +494,14 @@ class OIDC4VC { int count = 0; Future getSingleCredential({ - required IssuerTokenParameters issuerTokenParameters, required OpenIdConfiguration openIdConfiguration, - required String credentialType, - required List? types, - required String format, - required bool cryptoHolderBinding, - required OIDC4VCIDraftType oidc4vciDraftType, - required ClientAuthentication clientAuthentication, - required String? credentialIdentifier, - required Map? credentialDefinition, - required String? vct, - required ProofType proofType, - required String did, - required String issuer, - required String kid, - required String privateKey, required String accessToken, required String? nonce, required Dio dio, - required VCFormatType vcFormatType, + required Map credentialData, }) async { try { - final credentialData = await buildCredentialData( - nonce: nonce, - issuerTokenParameters: issuerTokenParameters, - openIdConfiguration: openIdConfiguration, - credentialType: credentialType, - types: types, - format: format, - credentialIdentifier: credentialIdentifier, - cryptoHolderBinding: cryptoHolderBinding, - oidc4vciDraftType: oidc4vciDraftType, - credentialDefinition: credentialDefinition, - clientAuthentication: clientAuthentication, - vct: vct, - proofType: proofType, - did: did, - issuer: issuer, - kid: kid, - privateKey: privateKey, - vcFormatType: vcFormatType, - ); - /// sign proof - final credentialEndpoint = readCredentialEndpoint(openIdConfiguration); final credentialHeaders = { @@ -723,26 +533,11 @@ class OIDC4VC { final nonce = e.response!.data['c_nonce'].toString(); final credentialResponseDataValue = await getSingleCredential( - issuerTokenParameters: issuerTokenParameters, openIdConfiguration: openIdConfiguration, - credentialType: credentialType, - types: types, - format: format, - cryptoHolderBinding: cryptoHolderBinding, - oidc4vciDraftType: oidc4vciDraftType, - credentialDefinition: credentialDefinition, - clientAuthentication: clientAuthentication, - vct: vct, - credentialIdentifier: null, - proofType: proofType, - did: did, - issuer: issuer, - kid: kid, - privateKey: privateKey, accessToken: accessToken, nonce: nonce, dio: dio, - vcFormatType: vcFormatType, + credentialData: credentialData, ); count = 0; return credentialResponseDataValue; diff --git a/packages/oidc4vc/test/src/oidc4vc_test.dart b/packages/oidc4vc/test/src/oidc4vc_test.dart index ab27a9062..509146086 100644 --- a/packages/oidc4vc/test/src/oidc4vc_test.dart +++ b/packages/oidc4vc/test/src/oidc4vc_test.dart @@ -564,67 +564,67 @@ void main() { ), ); - test('When getCredentialType receive url it returns json response', - () async { - final (credentialResponseData, deferredCredentialEndpoint, format) = - await oidc4vc.getCredential( - issuer: issuer, - credential: credential, - did: did, - clientId: did, - kid: kid, - privateKey: privateKey, - cryptoHolderBinding: true, - clientType: ClientType.did, - proofHeaderType: ProofHeaderType.kid, - oidc4vciDraftType: OIDC4VCIDraftType.draft11, - clientAuthentication: ClientAuthentication.clientId, - proofType: ProofType.jwt, - openIdConfiguration: OpenIdConfiguration.fromJson( - jsonDecode(openIdConfiguration) as Map, - ), - accessToken: accessToken, - cnonce: nonce, - dio: client, - vcFormatType: VCFormatType.jwtVcJson, - ); - - expect(credentialResponseData, [expecedCredentialResponse]); - expect( - deferredCredentialEndpoint, - 'https://talao.co/issuer/zxhaokccsi/deferred', - ); - expect(format, 'jwt_vc'); - }); - - test('throw Exception when token is not verified', () { - expect( - () async { - await oidc4vc.getCredential( - issuer: '', - credential: null, - did: '', - clientId: null, - kid: '', - privateKey: '', - cryptoHolderBinding: true, - clientType: ClientType.did, - proofHeaderType: ProofHeaderType.kid, - oidc4vciDraftType: OIDC4VCIDraftType.draft11, - clientAuthentication: ClientAuthentication.clientId, - proofType: ProofType.jwt, - openIdConfiguration: OpenIdConfiguration.fromJson( - jsonDecode(openIdConfiguration) as Map, - ), - accessToken: '', - cnonce: null, - dio: client, - vcFormatType: VCFormatType.jwtVcJson, - ); - }, - throwsA(isA()), - ); - }); + // test('When getCredentialType receive url it returns json response', + // () async { + // final (credentialResponseData, deferredCredentialEndpoint, format) = + // await oidc4vc.getCredential( + // issuer: issuer, + // credential: credential, + // did: did, + // clientId: did, + // kid: kid, + // privateKey: privateKey, + // cryptoHolderBinding: true, + // clientType: ClientType.did, + // proofHeaderType: ProofHeaderType.kid, + // oidc4vciDraftType: OIDC4VCIDraftType.draft11, + // clientAuthentication: ClientAuthentication.clientId, + // proofType: ProofType.jwt, + // openIdConfiguration: OpenIdConfiguration.fromJson( + // jsonDecode(openIdConfiguration) as Map, + // ), + // accessToken: accessToken, + // cnonce: nonce, + // dio: client, + // vcFormatType: VCFormatType.jwtVcJson, + // ); + + // expect(credentialResponseData, [expecedCredentialResponse]); + // expect( + // deferredCredentialEndpoint, + // 'https://talao.co/issuer/zxhaokccsi/deferred', + // ); + // expect(format, 'jwt_vc'); + // }); + + // test('throw Exception when token is not verified', () { + // expect( + // () async { + // await oidc4vc.getCredential( + // issuer: '', + // credential: null, + // did: '', + // clientId: null, + // kid: '', + // privateKey: '', + // cryptoHolderBinding: true, + // clientType: ClientType.did, + // proofHeaderType: ProofHeaderType.kid, + // oidc4vciDraftType: OIDC4VCIDraftType.draft11, + // clientAuthentication: ClientAuthentication.clientId, + // proofType: ProofType.jwt, + // openIdConfiguration: OpenIdConfiguration.fromJson( + // jsonDecode(openIdConfiguration) as Map, + // ), + // accessToken: '', + // cnonce: null, + // dio: client, + // vcFormatType: VCFormatType.jwtVcJson, + // ); + // }, + // throwsA(isA()), + // ); + // }); }); group('build token data', () { From f998a840ef5da2097be87385720657208e9bc6eb Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Wed, 6 Nov 2024 18:40:48 +0545 Subject: [PATCH 16/23] feat: Show deferred credential data to be sent #3054 --- .../cubit/qr_code_scan_cubit.dart | 1 + .../get_and_add_deffered_credential.dart | 21 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index f1cc1ba14..74304021e 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -863,6 +863,7 @@ class QRCodeScanCubit extends Cubit { blockchainType: walletCubit.state.currentAccount!.blockchainType, oidc4vciDraftType: customOidc4vcProfile.oidc4vciDraft, qrCodeScanCubit: qrCodeScanCubit, + profileCubit: profileCubit, ); } catch (e) { emitError(e); diff --git a/lib/oidc4vc/get_and_add_deffered_credential.dart b/lib/oidc4vc/get_and_add_deffered_credential.dart index 67d6edb51..35bd0314b 100644 --- a/lib/oidc4vc/get_and_add_deffered_credential.dart +++ b/lib/oidc4vc/get_and_add_deffered_credential.dart @@ -16,9 +16,10 @@ Future getAndAddDefferedCredential({ required BlockchainType blockchainType, required String? issuer, required QRCodeScanCubit qrCodeScanCubit, + required ProfileCubit profileCubit, }) async { - Map? credentialHeaders; - Map? body; + late Map credentialHeaders; + late Map body; final pendingInfo = credentialModel.pendingInfo!; @@ -49,6 +50,22 @@ Future getAndAddDefferedCredential({ body = {'transaction_id': transactionId}; } + if (profileCubit.state.model.isDeveloperMode) { + final value = await qrCodeScanCubit.showDataBeforeSending( + title: 'DEFERRED CREDENTIAL DATA', + data: body, + ); + + if (value) { + qrCodeScanCubit.completer = null; + } else { + qrCodeScanCubit.completer = null; + qrCodeScanCubit.resetNonceAndAccessTokenAndAuthorizationDetails(); + qrCodeScanCubit.goBack(); + return; + } + } + final dynamic encodedCredentialOrFutureToken = await oidc4vc.getDeferredCredential( credentialHeaders: credentialHeaders, From bfaad87b02baba2dc76c9ab0c2d7c1e10ea58b2b Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Wed, 6 Nov 2024 18:50:37 +0545 Subject: [PATCH 17/23] feat: Show par data to be sent #3054 --- .../cubit/qr_code_scan_cubit.dart | 8 +++++- .../get_authorization_uri_for_issuer.dart | 27 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 74304021e..86783e26b 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -1316,7 +1316,7 @@ class QRCodeScanCubit extends Cubit { emit(state.loading()); final scope = customOidc4vcProfile.scope; - await getAuthorizationUriForIssuer( + final authorizationUri = await getAuthorizationUriForIssuer( scannedResponse: state.uri.toString(), oidc4vc: oidc4vc, isEBSI: isEBSI, @@ -1338,7 +1338,13 @@ class QRCodeScanCubit extends Cubit { walletIssuer: Parameters.walletIssuer, useOAuthAuthorizationServerLink: useOauthServerAuthEndPoint(profileCubit.state.model), + profileCubit: profileCubit, + qrCodeScanCubit: qrCodeScanCubit, ); + + if (authorizationUri == null) return; + + await LaunchUrl.launchUri(authorizationUri); goBack(); } } catch (e) { diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 40a493a87..2f829e9bb 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:altme/app/app.dart'; import 'package:altme/app/shared/shared.dart'; +import 'package:altme/dashboard/dashboard.dart'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:did_kit/did_kit.dart'; @@ -9,7 +10,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:oidc4vc/oidc4vc.dart'; import 'package:uuid/uuid.dart'; -Future getAuthorizationUriForIssuer({ +Future getAuthorizationUriForIssuer({ required String scannedResponse, required OIDC4VC oidc4vc, required bool isEBSI, @@ -23,13 +24,15 @@ Future getAuthorizationUriForIssuer({ required ClientAuthentication clientAuthentication, required OIDC4VCIDraftType oidc4vciDraftType, required VCFormatType vcFormatType, - String? oAuthClientAttestation, - String? oAuthClientAttestationPop, required bool secureAuthorizedFlow, required DioClient client, required ProfileType profileType, required String walletIssuer, required bool useOAuthAuthorizationServerLink, + required ProfileCubit profileCubit, + required QRCodeScanCubit qrCodeScanCubit, + String? oAuthClientAttestation, + String? oAuthClientAttestationPop, }) async { /// this is first phase flow for authorization_code @@ -129,6 +132,22 @@ Future getAuthorizationUriForIssuer({ final parUrl = openIdConfiguration.pushedAuthorizationRequestEndpoint ?? '$authorizationEndpoint/par'; + if (profileCubit.state.model.isDeveloperMode) { + final value = await qrCodeScanCubit.showDataBeforeSending( + title: 'Pushed Authorization Request Data', + data: authorizationRequestParemeters, + ); + + if (value) { + qrCodeScanCubit.completer = null; + } else { + qrCodeScanCubit.completer = null; + qrCodeScanCubit.resetNonceAndAccessTokenAndAuthorizationDetails(); + qrCodeScanCubit.goBack(); + return null; + } + } + /// error we shuld get it from final response = await client.post( parUrl, @@ -157,5 +176,5 @@ Future getAuthorizationUriForIssuer({ Uri.https(url.authority, url.path, authorizationRequestParemeters); } - await LaunchUrl.launchUri(authorizationUri); + return authorizationUri; } From 0655ccfd0cb8ac893e08d4796c86348293d5e53e Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 7 Nov 2024 12:02:44 +0545 Subject: [PATCH 18/23] feat: Show response data for siopv2 flow and oidc4vp flow #3054 --- .../cubit/qr_code_scan_cubit.dart | 25 +++++++- lib/scan/cubit/scan_cubit.dart | 15 +++++ packages/oidc4vc/lib/src/oidc4vc.dart | 63 ++++++++++--------- 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 86783e26b..4b47a450a 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -1223,7 +1223,8 @@ class QRCodeScanCubit extends Cubit { final customOidc4vcProfile = profileCubit.state.model.profileSetting .selfSovereignIdentityOptions.customOidc4vcProfile; - final Response response = await oidc4vc.siopv2Flow( + final Map responseData = + await oidc4vc.getDataForSiopV2Flow( clientId: clientId, privateKey: privateKey, did: did, @@ -1232,8 +1233,28 @@ class QRCodeScanCubit extends Cubit { nonce: nonce, stateValue: stateValue, clientType: customOidc4vcProfile.clientType, - proofHeaderType: customOidc4vcProfile.proofHeader, + proofHeader: customOidc4vcProfile.proofHeader, + ); + + if (profileCubit.state.model.isDeveloperMode) { + final value = await showDataBeforeSending( + title: 'Response Data', + data: responseData, + ); + if (value) { + completer = null; + } else { + completer = null; + resetNonceAndAccessTokenAndAuthorizationDetails(); + goBack(); + return; + } + } + + final Response response = await oidc4vc.siopv2Flow( + redirectUri: redirectUri ?? responseUri!, dio: client.dio, + responseData: responseData, ); String? url; diff --git a/lib/scan/cubit/scan_cubit.dart b/lib/scan/cubit/scan_cubit.dart index d687820fc..385203526 100644 --- a/lib/scan/cubit/scan_cubit.dart +++ b/lib/scan/cubit/scan_cubit.dart @@ -618,6 +618,21 @@ class ScanCubit extends Cubit { body = responseData; } + if (profileCubit.state.model.isDeveloperMode) { + final value = await qrCodeScanCubit.showDataBeforeSending( + title: 'Response Data', + data: body, + ); + if (value) { + qrCodeScanCubit.completer = null; + } else { + qrCodeScanCubit.completer = null; + qrCodeScanCubit.resetNonceAndAccessTokenAndAuthorizationDetails(); + qrCodeScanCubit.goBack(); + return; + } + } + await Future.delayed(const Duration(seconds: 2)); final response = await client.dio.post( responseOrRedirectUri, diff --git a/packages/oidc4vc/lib/src/oidc4vc.dart b/packages/oidc4vc/lib/src/oidc4vc.dart index 24a17219c..72a7b1492 100644 --- a/packages/oidc4vc/lib/src/oidc4vc.dart +++ b/packages/oidc4vc/lib/src/oidc4vc.dart @@ -1398,7 +1398,7 @@ class OIDC4VC { } } - Future> siopv2Flow({ + Future> getDataForSiopV2Flow({ required String clientId, required String did, required String kid, @@ -1407,40 +1407,47 @@ class OIDC4VC { required String privateKey, required String? stateValue, required ClientType clientType, - required ProofHeaderType proofHeaderType, - required Dio dio, + required ProofHeaderType proofHeader, }) async { - try { - final private = jsonDecode(privateKey) as Map; + final private = jsonDecode(privateKey) as Map; + + final tokenParameters = VerifierTokenParameters( + privateKey: private, + did: did, + kid: kid, + audience: clientId, + credentials: [], + nonce: nonce, + mediaType: MediaType.basic, + clientType: clientType, + proofHeaderType: proofHeader, + clientId: clientId, + ); - final tokenParameters = VerifierTokenParameters( - privateKey: private, - did: did, - kid: kid, - audience: clientId, - credentials: [], - nonce: nonce, - mediaType: MediaType.basic, - clientType: clientType, - proofHeaderType: proofHeaderType, - clientId: clientId, - ); + // structures + final verifierIdToken = await getIdToken(tokenParameters); - // structures - final verifierIdToken = await getIdToken(tokenParameters); + final responseData = { + 'id_token': verifierIdToken, + }; - final responseHeaders = { - 'Content-Type': 'application/x-www-form-urlencoded', - }; + if (stateValue != null) { + responseData['state'] = stateValue; + } - final responseData = { - 'id_token': verifierIdToken, - }; + return responseData; + } - if (stateValue != null) { - responseData['state'] = stateValue; - } + Future> siopv2Flow({ + required String redirectUri, + required Dio dio, + required Map responseData, + }) async { + final responseHeaders = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + try { final response = await dio.post( redirectUri, options: Options( From 4cbbdac52975585514a67c172b0b7c153c83a53d Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 7 Nov 2024 13:32:54 +0545 Subject: [PATCH 19/23] version update: 2.16.5+540 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 322281a70..868c35fac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.16.4+539 +version: 2.16.5+540 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: From 9cf9aed98de098bb8c510a5e6c092a9d51c126cc Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 7 Nov 2024 15:46:19 +0545 Subject: [PATCH 20/23] feat: Use different format for emailpass #3066 --- .../credential_subject_type_extension.dart | 6 +++-- .../profile/models/profile_setting.dart | 15 ++++++++----- packages/oidc4vc/lib/src/vc_format_type.dart | 9 ++++++-- .../oidc4vc/test/src/vc_format_type_test.dart | 22 ++++++++++++++----- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/lib/app/shared/enum/type/credential_subject_type/credential_subject_type_extension.dart b/lib/app/shared/enum/type/credential_subject_type/credential_subject_type_extension.dart index b5c347dc3..38440acb2 100644 --- a/lib/app/shared/enum/type/credential_subject_type/credential_subject_type_extension.dart +++ b/lib/app/shared/enum/type/credential_subject_type/credential_subject_type_extension.dart @@ -767,7 +767,9 @@ extension CredentialSubjectTypeExtension on CredentialSubjectType { final discoverCardsOptions = profileSetting.discoverCardsOptions; - var format = VCFormatType.ldpVc.urlValue; + final isEmailPass = this == CredentialSubjectType.emailPass; + + var format = VCFormatType.ldpVc.urlValue(isEmailPass: isEmailPass); if (vcFormatType == VCFormatType.auto && discoverCardsOptions != null) { format = discoverCardsOptions.vcFormatTypeForAuto( @@ -775,7 +777,7 @@ extension CredentialSubjectTypeExtension on CredentialSubjectType { vcFormatType: assignedVCFormatType, ); } else { - format = vcFormatType.urlValue; + format = vcFormatType.urlValue(isEmailPass: isEmailPass); } switch (this) { diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index 20f5d2dd7..5abea141a 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -328,9 +328,14 @@ class DiscoverCardsOptions extends Equatable { required CredentialSubjectType credentialSubjectType, required VCFormatType vcFormatType, }) { - final ldpVcValue = VCFormatType.ldpVc.urlValue; - final jwtVcJsonValue = VCFormatType.jwtVcJson.urlValue; - final vcSdJWTValue = VCFormatType.vcSdJWT.urlValue; + final isEmailPass = + credentialSubjectType == CredentialSubjectType.emailPass; + + final ldpVcValue = VCFormatType.ldpVc.urlValue(isEmailPass: isEmailPass); + final jwtVcJsonValue = + VCFormatType.jwtVcJson.urlValue(isEmailPass: isEmailPass); + final vcSdJWTValue = + VCFormatType.vcSdJWT.urlValue(isEmailPass: isEmailPass); final isLdpVc = vcFormatType == VCFormatType.ldpVc; final isJwtVcJson = vcFormatType == VCFormatType.jwtVcJson; @@ -416,10 +421,10 @@ class DiscoverCardsOptions extends Equatable { case CredentialSubjectType.identityCredential: case CredentialSubjectType.eudiPid: case CredentialSubjectType.pid: - return VCFormatType.ldpVc.urlValue; + return VCFormatType.ldpVc.urlValue(isEmailPass: isEmailPass); } - return VCFormatType.ldpVc.urlValue; + return VCFormatType.ldpVc.urlValue(isEmailPass: isEmailPass); } @override diff --git a/packages/oidc4vc/lib/src/vc_format_type.dart b/packages/oidc4vc/lib/src/vc_format_type.dart index f9675b18f..b1f3b4c18 100644 --- a/packages/oidc4vc/lib/src/vc_format_type.dart +++ b/packages/oidc4vc/lib/src/vc_format_type.dart @@ -33,7 +33,7 @@ extension VCFormatTypeX on VCFormatType { } } - String get urlValue { + String urlValue({required bool isEmailPass}) { switch (this) { case VCFormatType.ldpVc: return 'ldp_vc'; @@ -44,7 +44,12 @@ extension VCFormatTypeX on VCFormatType { case VCFormatType.jwtVcJsonLd: return 'jwt_vc_json-ld'; case VCFormatType.vcSdJWT: - return 'vcsd-jwt'; + if (isEmailPass) { + return 'vc_sd_jwt'; + } else { + return 'vcsd-jwt'; + } + case VCFormatType.auto: return 'auto'; } diff --git a/packages/oidc4vc/test/src/vc_format_type_test.dart b/packages/oidc4vc/test/src/vc_format_type_test.dart index deb3714d2..b55436747 100644 --- a/packages/oidc4vc/test/src/vc_format_type_test.dart +++ b/packages/oidc4vc/test/src/vc_format_type_test.dart @@ -20,11 +20,23 @@ void main() { }); test('urlValue', () { - expect(VCFormatType.ldpVc.urlValue, 'ldp_vc'); - expect(VCFormatType.jwtVc.urlValue, 'jwt_vc'); - expect(VCFormatType.jwtVcJson.urlValue, 'jwt_vc_json'); - expect(VCFormatType.jwtVcJsonLd.urlValue, 'jwt_vc_json-ld'); - expect(VCFormatType.vcSdJWT.urlValue, 'vcsd-jwt'); + expect(VCFormatType.ldpVc.urlValue(isEmailPass: true), 'ldp_vc'); + expect(VCFormatType.ldpVc.urlValue(isEmailPass: false), 'ldp_vc'); + expect(VCFormatType.jwtVc.urlValue(isEmailPass: true), 'jwt_vc'); + expect(VCFormatType.jwtVc.urlValue(isEmailPass: false), 'jwt_vc'); + expect(VCFormatType.jwtVcJson.urlValue(isEmailPass: true), 'jwt_vc_json'); + expect( + VCFormatType.jwtVcJson.urlValue(isEmailPass: false), 'jwt_vc_json'); + expect( + VCFormatType.jwtVcJsonLd.urlValue(isEmailPass: true), + 'jwt_vc_json-ld', + ); + expect( + VCFormatType.jwtVcJsonLd.urlValue(isEmailPass: false), + 'jwt_vc_json-ld', + ); + expect(VCFormatType.vcSdJWT.urlValue(isEmailPass: true), 'vc_sd_jwt'); + expect(VCFormatType.vcSdJWT.urlValue(isEmailPass: false), 'vcsd-jwt'); }); test('supportCryptoCredential', () { From 827c0f6cd9e66d165fe83c78649505e555026a00 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 7 Nov 2024 17:05:49 +0545 Subject: [PATCH 21/23] feat: Update oidc4vc tests --- packages/oidc4vc/test/src/oidc4vc_test.dart | 139 ++++++-------------- 1 file changed, 43 insertions(+), 96 deletions(-) diff --git a/packages/oidc4vc/test/src/oidc4vc_test.dart b/packages/oidc4vc/test/src/oidc4vc_test.dart index 509146086..370f40d94 100644 --- a/packages/oidc4vc/test/src/oidc4vc_test.dart +++ b/packages/oidc4vc/test/src/oidc4vc_test.dart @@ -253,10 +253,16 @@ void main() { '[{\"type\":\"openid_credential\",\"credential_configuration_id\":\"EmailPass\"}]', }; - dioAdapter.onGet( - 'https://talao.co/issuer/mfyttabosy/.well-known/openid-credential-issuer', - (request) => request.reply(200, jsonDecode(openIdConfiguration)), - ); + dioAdapter + ..onGet( + 'https://talao.co/issuer/mfyttabosy/.well-known/openid-credential-issuer', + (request) => request.reply(200, jsonDecode(openIdConfiguration)), + ) + ..onGet( + 'https://talao.co/issuer/mfyttabosy/.well-known/openid-configuration', + (request) => request.reply(200, jsonDecode(openIdConfiguration)), + ); + final (authorizationEndpoint, authorizationRequestParemeters, _) = await oidc4vc.getAuthorizationData( selectedCredentials: selectedCredentials, @@ -524,26 +530,6 @@ void main() { }); group('OIC4VC request credential', () { - const issuer = 'https://talao.co/issuer/zxhaokccsi'; - - const credential = { - 'format': 'jwt_vc', - 'types': [ - 'VerifiableCredential', - 'VerifiableAttestation', - 'VerifiableDiploma2', - ], - }; - - const did = - 'did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9Kbrbpg5is8LfTLuQ1RsW5r7s7ZjbDDFbDgy1tLrdc7Bj3itBGQkuGUQyfzKhFqbUNW2PqJPMSSzWoF2DGSvDSijCtJtYCSRsjSVLrwu5oHNbnPFvSEC4iRZPpU6B6nExRBTa'; - - const kid = - 'did:key:z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9Kbrbpg5is8LfTLuQ1RsW5r7s7ZjbDDFbDgy1tLrdc7Bj3itBGQkuGUQyfzKhFqbUNW2PqJPMSSzWoF2DGSvDSijCtJtYCSRsjSVLrwu5oHNbnPFvSEC4iRZPpU6B6nExRBTa#z2dmzD81cgPx8Vki7JbuuMmFYrWPgYoytykUZ3eyqht1j9Kbrbpg5is8LfTLuQ1RsW5r7s7ZjbDDFbDgy1tLrdc7Bj3itBGQkuGUQyfzKhFqbUNW2PqJPMSSzWoF2DGSvDSijCtJtYCSRsjSVLrwu5oHNbnPFvSEC4iRZPpU6B6nExRBTa'; - - const privateKey = - '{"kty":"EC","crv":"P-256","d":"amrwK13ZiYoJ5g0fc6MvXc86RB9ID8VuK_dMowU68FE","x":"fJQ2c9P_YDep3jzidwykcSlyoC4omqBvd9RHP1nz0cw","y":"K7VxrW-S1ONuX5cxrWIltF36ac1K8kj9as_o5cyc2zk"}'; - const openIdConfiguration = '{"authorization_server":"https://talao.co/issuer/zxhaokccsi","credential_endpoint":"https://talao.co/issuer/zxhaokccsi/credential","credential_issuer":"https://talao.co/issuer/zxhaokccsi","subject_syntax_types_supported":null,"token_endpoint":null,"batch_endpoint":null,"authorization_endpoint":null,"subject_trust_frameworks_supported":null,"credentials_supported":[{"display":[{"locale":"en-US","name":"EU Diploma","description":"This the official EBSI VC Diploma","text_color":"#FFFFFF","background_color":"#3B6F6D","background_image":{"url":"https://i.ibb.co/CHqjxrJ/dbc-card-hig-res.png","alt_text":"Connected open cubes in blue with one orange cube as a background of the card"},"logo":{"url":"https://dutchblockchaincoalition.org/assets/images/icons/Logo-DBC.png","alt_text":"An orange block shape, with the text Dutch Blockchain Coalition next to it, portraying the logo of the Dutch Blockchain Coalition."}}],"format":"jwt_vc","trust_framework":{"name":"ebsi","type":"Accreditation","uri":"TIR link towards accreditation"},"types":["VerifiableCredential","VerifiableAttestation","VerifiableDiploma2"],"id":null,"scope":null,"credentialSubject":{"dateOfBirth":{"display":[{"locale":"en-US","name":"Birth Date"},{"locale":"fr-FR","name":"Date de naissance"}]},"familyName":{"display":[{"locale":"en-US","name":"Family Name"},{"locale":"fr-FR","name":"Nom"}]},"givenNames":{"display":[{"locale":"en-US","name":"First Name"},{"locale":"fr-FR","name":"Prénom"}]}}},{"display":[{"locale":"en-US","name":"Individual attestation","description":"This is the EBSI Individual Verifiable Attestation","text_color":"#FFFFFF","background_color":"#3B6F6D","background_image":null,"logo":null}],"format":"jwt_vc","trust_framework":{"name":"ebsi","type":"Accreditation","uri":"TIR link towards accreditation"},"types":["VerifiableCredential","VerifiableAttestation","IndividualVerifiableAttestation"],"id":null,"scope":null,"credentialSubject":{"dateOfBirth":{"display":[{"locale":"en-US","name":"Birth Date"},{"locale":"fr-FR","name":"Date de naissance"}]},"familyName":{"display":[{"locale":"en-US","name":"Family Name"},{"locale":"fr-FR","name":"Nom"}]},"firstName":{"display":[{"locale":"en-US","name":"First Name"},{"locale":"fr-FR","name":"Prénom"}]},"issuing_country":{"display":[{"locale":"en-US","name":"Issued by"},{"locale":"fr-FR","name":"Délivré par"}]},"placeOfBirth":{"display":[{"locale":"en-US","name":"Birth Place"},{"locale":"fr-FR","name":"Lieu de naissance"}]}}},{"display":[{"locale":"en-GB","name":"Email proof","description":"This is a verifiable credential","text_color":null,"background_color":null,"background_image":null,"logo":null}],"format":"jwt_vc","trust_framework":{"name":"ebsi","type":"Accreditation","uri":"TIR link towards accreditation"},"types":["VerifiableCredential","EmailPass"],"id":null,"scope":null,"credentialSubject":null},{"display":[{"locale":"en-GB","name":"Verifiable Id","description":"This is a verifiable credential","text_color":null,"background_color":null,"background_image":null,"logo":null}],"format":"jwt_vc","trust_framework":{"name":"ebsi","type":"Accreditation","uri":"TIR link towards accreditation"},"types":["VerifiableCredential","VerifiableAttestation","VerifiableId"],"id":null,"scope":null,"credentialSubject":null}],"credential_configurations_supported":null,"deferred_credential_endpoint":"https://talao.co/issuer/zxhaokccsi/deferred","service_documentation":null,"credential_manifest":null,"credential_manifests":null,"issuer":null,"jwks_uri":null,"grant_types_supported":null}'; @@ -564,67 +550,20 @@ void main() { ), ); - // test('When getCredentialType receive url it returns json response', - // () async { - // final (credentialResponseData, deferredCredentialEndpoint, format) = - // await oidc4vc.getCredential( - // issuer: issuer, - // credential: credential, - // did: did, - // clientId: did, - // kid: kid, - // privateKey: privateKey, - // cryptoHolderBinding: true, - // clientType: ClientType.did, - // proofHeaderType: ProofHeaderType.kid, - // oidc4vciDraftType: OIDC4VCIDraftType.draft11, - // clientAuthentication: ClientAuthentication.clientId, - // proofType: ProofType.jwt, - // openIdConfiguration: OpenIdConfiguration.fromJson( - // jsonDecode(openIdConfiguration) as Map, - // ), - // accessToken: accessToken, - // cnonce: nonce, - // dio: client, - // vcFormatType: VCFormatType.jwtVcJson, - // ); - - // expect(credentialResponseData, [expecedCredentialResponse]); - // expect( - // deferredCredentialEndpoint, - // 'https://talao.co/issuer/zxhaokccsi/deferred', - // ); - // expect(format, 'jwt_vc'); - // }); - - // test('throw Exception when token is not verified', () { - // expect( - // () async { - // await oidc4vc.getCredential( - // issuer: '', - // credential: null, - // did: '', - // clientId: null, - // kid: '', - // privateKey: '', - // cryptoHolderBinding: true, - // clientType: ClientType.did, - // proofHeaderType: ProofHeaderType.kid, - // oidc4vciDraftType: OIDC4VCIDraftType.draft11, - // clientAuthentication: ClientAuthentication.clientId, - // proofType: ProofType.jwt, - // openIdConfiguration: OpenIdConfiguration.fromJson( - // jsonDecode(openIdConfiguration) as Map, - // ), - // accessToken: '', - // cnonce: null, - // dio: client, - // vcFormatType: VCFormatType.jwtVcJson, - // ); - // }, - // throwsA(isA()), - // ); - // }); + test('When getCredentialType receive url it returns json response', + () async { + final credentialResponseData = await oidc4vc.getSingleCredential( + openIdConfiguration: OpenIdConfiguration.fromJson( + jsonDecode(openIdConfiguration) as Map, + ), + accessToken: accessToken, + nonce: nonce, + dio: client, + credentialData: {}, + ); + + expect(credentialResponseData, expecedCredentialResponse); + }); }); group('build token data', () { @@ -792,18 +731,26 @@ void main() { expect(isVerified, VerificationType.verified); }); - test('returns VerificationType.unKnown', () async { - final isVerified = await oidc4vc.verifyEncodedData( - issuer: issuer, - jwt: jwt, - issuerKid: issuerKid2, - dio: client, - fromStatusList: false, - isCachingEnabled: false, - publicJwk: null, - useOAuthAuthorizationServerLink: false, + test('throws exception KID_DOES_NOT_MATCH_DIDDOCUMENT', () async { + expect( + () async => oidc4vc.verifyEncodedData( + issuer: issuer, + jwt: jwt, + issuerKid: issuerKid2, + dio: client, + fromStatusList: false, + isCachingEnabled: false, + publicJwk: null, + useOAuthAuthorizationServerLink: false, + ), + throwsA( + isA().having( + (p0) => p0.toString(), + 'toString()', + 'Exception: KID_DOES_NOT_MATCH_DIDDOCUMENT', + ), + ), ); - expect(isVerified, VerificationType.unKnown); }); test('returns VerificationType.notVerified', () async { From d94783e0bc884a861244974580d1ae2f4f8cd6b8 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Fri, 8 Nov 2024 13:35:08 +0545 Subject: [PATCH 22/23] test update --- .../helper_functions/helper_functions.dart | 5 +- ...redential_subject_type_extension_test.dart | 348 +++++------------- .../helper_functions_test.dart | 62 +++- .../view/help_center_menu_test.dart | 66 ++-- .../drawer/src/view/drawer_page_test.dart | 47 --- .../view/onboarding_gen_phrase_test.dart | 3 + 6 files changed, 185 insertions(+), 346 deletions(-) diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 460d09627..380876704 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -1314,6 +1314,7 @@ ResponseString getErrorResponseString(String errorString) { return ResponseString.RESPONSE_STRING_theWalletIsNotRegistered; case 'invalid_grant': + case 'issuance_pending': case 'invalid_token': return ResponseString.RESPONSE_STRING_credentialIssuanceDenied; @@ -1329,10 +1330,6 @@ ResponseString getErrorResponseString(String errorString) { case 'server_error': return ResponseString.RESPONSE_STRING_theServiceIsNotAvailable; - case 'issuance_pending': - return ResponseString - .RESPONSE_STRING_theIssuanceOfThisCredentialIsPending; - case 'invalid_client': return ResponseString.RESPONSE_STRING_invalidClientErrorDescription; diff --git a/test/app/shared/enum/credential_subject_type/credential_subject_type_extension_test.dart b/test/app/shared/enum/credential_subject_type/credential_subject_type_extension_test.dart index b7db3d0fb..ef890beda 100644 --- a/test/app/shared/enum/credential_subject_type/credential_subject_type_extension_test.dart +++ b/test/app/shared/enum/credential_subject_type/credential_subject_type_extension_test.dart @@ -920,253 +920,109 @@ void main() { expect(CredentialSubjectType.pid.supportSingleOnly, false); }); - test('CredentialSubjectType getVCFormatType returns correct value', () { - expect( - CredentialSubjectType.ethereumAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - expect( - CredentialSubjectType.fantomAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - expect( - CredentialSubjectType.polygonAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - expect( - CredentialSubjectType.binanceAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - expect( - CredentialSubjectType.etherlinkAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - expect( - CredentialSubjectType.tezosAssociatedWallet.getVCFormatType, - VCFormatType.values, - ); - - expect( - CredentialSubjectType.over13.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.over15.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.over21.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.over50.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.over65.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.gender.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.ageRange.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.defiCompliance.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.tezotopiaMembership.getVCFormatType, - [VCFormatType.ldpVc], - ); - expect( - CredentialSubjectType.chainbornMembership.getVCFormatType, - [VCFormatType.ldpVc], - ); - - expect(CredentialSubjectType.verifiableIdCard.getVCFormatType, [ - VCFormatType.ldpVc, - VCFormatType.jwtVcJson, - VCFormatType.vcSdJWT, - VCFormatType.jwtVc, - ]); - - expect( - CredentialSubjectType.identityCredential.getVCFormatType, - [VCFormatType.vcSdJWT], - ); - expect( - CredentialSubjectType.eudiPid.getVCFormatType, - [VCFormatType.vcSdJWT], - ); - expect(CredentialSubjectType.pid.getVCFormatType, [VCFormatType.vcSdJWT]); - - expect(CredentialSubjectType.over18.getVCFormatType, [ - VCFormatType.ldpVc, - VCFormatType.jwtVcJson, - ]); - - expect( - CredentialSubjectType.phonePass.getVCFormatType, - [VCFormatType.ldpVc, VCFormatType.jwtVcJson], - ); - expect( - CredentialSubjectType.livenessCard.getVCFormatType, - [VCFormatType.ldpVc, VCFormatType.jwtVcJson], - ); - expect( - CredentialSubjectType.emailPass.getVCFormatType, - [VCFormatType.ldpVc, VCFormatType.jwtVcJson], - ); - - expect( - CredentialSubjectType.nationality.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.identityPass.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.passportFootprint.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.residentCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.voucher.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.tezVoucher.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.diplomaCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.twitterCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.walletCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.tezosPooAddress.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.ethereumPooAddress.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.fantomPooAddress.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.polygonPooAddress.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.binancePooAddress.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.certificateOfEmployment.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.defaultCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); + test('returns correct VCFormatType values for each CredentialSubjectType', + () { + void verifyVCFormatType(CredentialSubjectType subjectType, + List expectedValues) { + expect( + subjectType.getVCFormatType, + equals(expectedValues), + reason: 'Failed for $subjectType', + ); + } - expect( - CredentialSubjectType.learningAchievement.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.professionalExperienceAssessment.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.professionalSkillAssessment.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.professionalStudentCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.selfIssued.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.studentCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.aragoPass.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.aragoEmailPass.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.aragoIdentityCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.aragoLearningAchievement.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.aragoOver18.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.pcdsAgentCertificate.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.euDiplomaCard.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.euVerifiableId.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.kycAgeCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.kycCountryOfResidence.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.proofOfTwitterStats.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.civicPassCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.employeeCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); - expect( - CredentialSubjectType.legalPersonalCredential.getVCFormatType, - [VCFormatType.jwtVc], - ); + for (final type in CredentialSubjectType.values) { + switch (type) { + case CredentialSubjectType.ethereumAssociatedWallet: + case CredentialSubjectType.fantomAssociatedWallet: + case CredentialSubjectType.polygonAssociatedWallet: + case CredentialSubjectType.binanceAssociatedWallet: + case CredentialSubjectType.tezosAssociatedWallet: + case CredentialSubjectType.etherlinkAssociatedWallet: + verifyVCFormatType(type, VCFormatType.values); + + case CredentialSubjectType.over13: + case CredentialSubjectType.over15: + case CredentialSubjectType.over21: + case CredentialSubjectType.over50: + case CredentialSubjectType.over65: + case CredentialSubjectType.ageRange: + case CredentialSubjectType.gender: + case CredentialSubjectType.chainbornMembership: + case CredentialSubjectType.tezotopiaMembership: + case CredentialSubjectType.defiCompliance: + verifyVCFormatType(type, [VCFormatType.ldpVc, VCFormatType.auto]); + + case CredentialSubjectType.over18: + case CredentialSubjectType.livenessCard: + case CredentialSubjectType.phonePass: + verifyVCFormatType(type, [ + VCFormatType.ldpVc, + VCFormatType.jwtVcJson, + VCFormatType.auto, + ]); + + case CredentialSubjectType.verifiableIdCard: + verifyVCFormatType(type, [ + VCFormatType.ldpVc, + VCFormatType.jwtVcJson, + VCFormatType.vcSdJWT, + VCFormatType.jwtVc, + VCFormatType.auto, + ]); + + case CredentialSubjectType.emailPass: + verifyVCFormatType(type, [ + VCFormatType.ldpVc, + VCFormatType.jwtVcJson, + VCFormatType.auto, + VCFormatType.vcSdJWT, + ]); + + case CredentialSubjectType.identityCredential: + case CredentialSubjectType.eudiPid: + case CredentialSubjectType.pid: + verifyVCFormatType(type, [VCFormatType.vcSdJWT, VCFormatType.auto]); + + case CredentialSubjectType.nationality: + case CredentialSubjectType.identityPass: + case CredentialSubjectType.passportFootprint: + case CredentialSubjectType.residentCard: + case CredentialSubjectType.voucher: + case CredentialSubjectType.tezVoucher: + case CredentialSubjectType.diplomaCard: + case CredentialSubjectType.twitterCard: + case CredentialSubjectType.walletCredential: + case CredentialSubjectType.tezosPooAddress: + case CredentialSubjectType.ethereumPooAddress: + case CredentialSubjectType.fantomPooAddress: + case CredentialSubjectType.polygonPooAddress: + case CredentialSubjectType.binancePooAddress: + case CredentialSubjectType.certificateOfEmployment: + case CredentialSubjectType.defaultCredential: + case CredentialSubjectType.learningAchievement: + case CredentialSubjectType.professionalExperienceAssessment: + case CredentialSubjectType.professionalSkillAssessment: + case CredentialSubjectType.professionalStudentCard: + case CredentialSubjectType.selfIssued: + case CredentialSubjectType.studentCard: + case CredentialSubjectType.aragoPass: + case CredentialSubjectType.aragoEmailPass: + case CredentialSubjectType.aragoIdentityCard: + case CredentialSubjectType.aragoLearningAchievement: + case CredentialSubjectType.aragoOver18: + case CredentialSubjectType.pcdsAgentCertificate: + case CredentialSubjectType.euDiplomaCard: + case CredentialSubjectType.euVerifiableId: + case CredentialSubjectType.kycAgeCredential: + case CredentialSubjectType.kycCountryOfResidence: + case CredentialSubjectType.proofOfTwitterStats: + case CredentialSubjectType.civicPassCredential: + case CredentialSubjectType.employeeCredential: + case CredentialSubjectType.legalPersonalCredential: + verifyVCFormatType(type, [VCFormatType.jwtVc, VCFormatType.auto]); + } + } }); test('CredentialSubjectType order returns correct value', () { diff --git a/test/app/shared/helper_functions/helper_functions_test.dart b/test/app/shared/helper_functions/helper_functions_test.dart index ec3ff4115..e4ebca673 100644 --- a/test/app/shared/helper_functions/helper_functions_test.dart +++ b/test/app/shared/helper_functions/helper_functions_test.dart @@ -936,7 +936,7 @@ void main() { ResponseString.RESPONSE_STRING_credentialIssuanceDenied, ); expect( - getErrorResponseString('invalid_client'), + getErrorResponseString('issuance_pending'), ResponseString.RESPONSE_STRING_credentialIssuanceDenied, ); expect( @@ -965,8 +965,20 @@ void main() { ); expect( - getErrorResponseString('issuance_pending'), - ResponseString.RESPONSE_STRING_theIssuanceOfThisCredentialIsPending, + getErrorResponseString('invalid_client'), + ResponseString.RESPONSE_STRING_invalidClientErrorDescription, + ); + + expect( + getErrorResponseString('vp_formats_not_supported'), + ResponseString + .RESPONSE_STRING_vpFormatsNotSupportedErrorDescription, + ); + + expect( + getErrorResponseString('invalid_presentation_definition_uri'), + ResponseString + .RESPONSE_STRING_invalidPresentationDefinitionUriErrorDescription, ); expect( @@ -1090,7 +1102,7 @@ void main() { clientMetaData: null, credentialsToBePresented: [], ), - (true, false, false, false), + [VCFormatType.ldpVc], ); }); @@ -1132,7 +1144,13 @@ void main() { clientMetaData: null, credentialsToBePresented: [], ), - (false, true, false, false), + [ + VCFormatType.ldpVc, + VCFormatType.jwtVc, + VCFormatType.jwtVcJson, + VCFormatType.jwtVcJsonLd, + VCFormatType.vcSdJWT, + ], ); }); @@ -1150,7 +1168,13 @@ void main() { clientMetaData: null, credentialsToBePresented: [], ), - (false, false, true, false), + [ + VCFormatType.ldpVc, + VCFormatType.jwtVc, + VCFormatType.jwtVcJson, + VCFormatType.jwtVcJsonLd, + VCFormatType.vcSdJWT, + ], ); }); @@ -1168,7 +1192,13 @@ void main() { clientMetaData: null, credentialsToBePresented: [], ), - (false, false, false, true), + [ + VCFormatType.ldpVc, + VCFormatType.jwtVc, + VCFormatType.jwtVcJson, + VCFormatType.jwtVcJsonLd, + VCFormatType.vcSdJWT, + ], ); }); @@ -1190,7 +1220,7 @@ void main() { }, credentialsToBePresented: [], ), - (false, false, true, false), + [VCFormatType.jwtVcJson], ); }); @@ -1212,7 +1242,7 @@ void main() { }, credentialsToBePresented: [], ), - (false, false, false, true), + [VCFormatType.vcSdJWT], ); }); }); @@ -1506,7 +1536,7 @@ void main() { associatedAddress: 'tezosAddress', ), ), - 'tezosAddress', + ('tezosAddress', BlockchainType.tezos), ); expect( getWalletAddress( @@ -1517,7 +1547,7 @@ void main() { associatedAddress: 'ethereumAddress', ), ), - 'ethereumAddress', + ('ethereumAddress', BlockchainType.ethereum), ); expect( getWalletAddress( @@ -1528,7 +1558,7 @@ void main() { associatedAddress: 'polygonAddress', ), ), - 'polygonAddress', + ('polygonAddress', BlockchainType.polygon), ); expect( getWalletAddress( @@ -1539,7 +1569,7 @@ void main() { associatedAddress: 'address', ), ), - 'address', + ('address', BlockchainType.binance), ); expect( getWalletAddress( @@ -1550,7 +1580,7 @@ void main() { associatedAddress: 'fantomAddress', ), ), - 'fantomAddress', + ('fantomAddress', BlockchainType.fantom), ); expect( getWalletAddress( @@ -1561,7 +1591,7 @@ void main() { associatedAddress: 'etherlinkAddress', ), ), - 'etherlinkAddress', + ('etherlinkAddress', BlockchainType.etherlink), ); expect( getWalletAddress( @@ -1571,7 +1601,7 @@ void main() { issuedBy: const Author('name'), ), ), - isNull, + (null, null), ); }); diff --git a/test/dashboard/drawer/help_center/view/help_center_menu_test.dart b/test/dashboard/drawer/help_center/view/help_center_menu_test.dart index a4b98f790..9d65b4efa 100644 --- a/test/dashboard/drawer/help_center/view/help_center_menu_test.dart +++ b/test/dashboard/drawer/help_center/view/help_center_menu_test.dart @@ -136,38 +136,38 @@ void main() { ).called(1); }); - testWidgets('navigates to FAQsPage when "faqs" is tapped', (tester) async { - when(() => mockProfileCubit.state).thenReturn( - ProfileState(model: ProfileModel.empty()), - ); - - await tester.pumpApp( - MockNavigatorProvider( - navigator: navigator, - child: MultiBlocProvider( - providers: [ - BlocProvider.value(value: mockProfileCubit), - BlocProvider.value(value: mockFlavorCubit), - ], - child: HelpCenterView(profileCubit: mockProfileCubit), - ), - ), - ); - - expect(find.text('Frequently Asked Questions (FAQs)'), findsOneWidget); - - await tester.tap(find.text('Frequently Asked Questions (FAQs)')); - await tester.pumpAndSettle(); - - verify( - () => navigator.push( - any( - that: isRoute( - whereName: equals('/FAQsPage'), - ), - ), - ), - ).called(1); - }); + // testWidgets('navigates to FAQsPage when "faqs" is tapped', (tester) async { + // when(() => mockProfileCubit.state).thenReturn( + // ProfileState(model: ProfileModel.empty()), + // ); + + // await tester.pumpApp( + // MockNavigatorProvider( + // navigator: navigator, + // child: MultiBlocProvider( + // providers: [ + // BlocProvider.value(value: mockProfileCubit), + // BlocProvider.value(value: mockFlavorCubit), + // ], + // child: HelpCenterView(profileCubit: mockProfileCubit), + // ), + // ), + // ); + + // expect(find.text('Frequently Asked Questions (FAQs)'), findsOneWidget); + + // await tester.tap(find.text('Frequently Asked Questions (FAQs)')); + // await tester.pumpAndSettle(); + + // verify( + // () => navigator.push( + // any( + // that: isRoute( + // whereName: equals('/FAQsPage'), + // ), + // ), + // ), + // ).called(1); + // }); }); } diff --git a/test/dashboard/drawer/src/view/drawer_page_test.dart b/test/dashboard/drawer/src/view/drawer_page_test.dart index f6b5cecc8..053357a50 100644 --- a/test/dashboard/drawer/src/view/drawer_page_test.dart +++ b/test/dashboard/drawer/src/view/drawer_page_test.dart @@ -183,53 +183,6 @@ void main() { } }); - testWidgets( - 'navigates to SSIMenu when displaySelfSovereignIdentity is enabled ' - 'and "ssi" is tapped', (tester) async { - when(() => mockProfileCubit.state).thenReturn( - ProfileState(model: ProfileModel.empty()), - ); - - await tester.pumpApp( - MockNavigatorProvider( - navigator: navigator, - child: MultiBlocProvider( - providers: [ - BlocProvider.value(value: mockProfileCubit), - BlocProvider.value(value: mockFlavorCubit), - ], - child: DrawerView(profileCubit: mockProfileCubit), - ), - ), - ); - - expect(find.text('Self-Sovereign Identity (DID)'), findsOneWidget); - expect( - find.text( - 'Manage your Decentralized ID and backup or restore your credentials', - ), - findsOneWidget, - ); - - await tester.scrollUntilVisible( - find.text('Self-Sovereign Identity (DID)'), - 0, - ); - - await tester.tap(find.text('Self-Sovereign Identity (DID)')); - await tester.pumpAndSettle(); - - verify( - () => navigator.push( - any( - that: isRoute( - whereName: equals('/ssiMenu'), - ), - ), - ), - ).called(1); - }); - testWidgets( 'setDeveloperModeStatus is called when displayDeveloperMode is enabled ' 'and "developerMode" is tapped', (tester) async { diff --git a/test/onboarding/gen_phrase/view/onboarding_gen_phrase_test.dart b/test/onboarding/gen_phrase/view/onboarding_gen_phrase_test.dart index 8478a4327..b8f8715da 100644 --- a/test/onboarding/gen_phrase/view/onboarding_gen_phrase_test.dart +++ b/test/onboarding/gen_phrase/view/onboarding_gen_phrase_test.dart @@ -164,6 +164,9 @@ void main() { BlocProvider.value( value: altmeChatSupportCubit, ), + BlocProvider.value( + value: matrixNotificationCubit, + ), BlocProvider.value(value: profileCubit), ], child: const OnBoardingGenPhrasePage(), From 10c7853695370e1516810b120a18fd8336e26c9f Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Fri, 8 Nov 2024 14:47:24 +0545 Subject: [PATCH 23/23] feat: Add continue button while showing data #3054 --- .../json_viewer/view/json_viewer_page.dart | 31 +++++++------------ .../cubit/qr_code_scan_cubit.dart | 4 +-- .../get_and_add_deffered_credential.dart | 2 +- .../get_authorization_uri_for_issuer.dart | 2 +- lib/oidc4vc/get_credential.dart | 4 +-- lib/scan/cubit/scan_cubit.dart | 2 +- lib/splash/bloclisteners/blocklisteners.dart | 24 +++++++++++--- 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/lib/dashboard/json_viewer/view/json_viewer_page.dart b/lib/dashboard/json_viewer/view/json_viewer_page.dart index 7c4a01d8d..b4ea4c498 100644 --- a/lib/dashboard/json_viewer/view/json_viewer_page.dart +++ b/lib/dashboard/json_viewer/view/json_viewer_page.dart @@ -8,23 +8,19 @@ class JsonViewerPage extends StatelessWidget { super.key, required this.title, required this.data, - required this.showContinueButton, }); final String title; final String data; - final bool showContinueButton; static Route route({ required String title, required String data, - bool showContinueButton = false, }) => MaterialPageRoute( builder: (_) => JsonViewerPage( title: title, data: data, - showContinueButton: showContinueButton, ), settings: const RouteSettings(name: '/JsonViewerPage'), ); @@ -34,7 +30,6 @@ class JsonViewerPage extends StatelessWidget { return JsonViewerView( title: title, data: data, - showContinueButton: showContinueButton, ); } } @@ -44,12 +39,10 @@ class JsonViewerView extends StatelessWidget { super.key, required this.title, required this.data, - required this.showContinueButton, }); final String title; final String data; - final bool showContinueButton; @override Widget build(BuildContext context) { @@ -64,19 +57,17 @@ class JsonViewerView extends StatelessWidget { ), padding: const EdgeInsets.symmetric(horizontal: 10), body: JsonViewWidget(data: data), - navigation: !showContinueButton - ? null - : Padding( - padding: const EdgeInsets.all( - Sizes.spaceSmall, - ), - child: MyElevatedButton( - text: context.l10n.continueString, - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), + navigation: Padding( + padding: const EdgeInsets.all( + Sizes.spaceSmall, + ), + child: MyElevatedButton( + text: context.l10n.continueString, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); } } diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 4b47a450a..dcf57ca4c 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -1238,7 +1238,7 @@ class QRCodeScanCubit extends Cubit { if (profileCubit.state.model.isDeveloperMode) { final value = await showDataBeforeSending( - title: 'Response Data', + title: 'RESPONSE REQUEST', data: responseData, ); if (value) { @@ -1437,7 +1437,7 @@ class QRCodeScanCubit extends Cubit { if (profileCubit.state.model.isDeveloperMode) { final value = await showDataBeforeSending( - title: 'TOKEN DATA', + title: 'TOKEN REQUEST', data: tokenData, ); if (value) { diff --git a/lib/oidc4vc/get_and_add_deffered_credential.dart b/lib/oidc4vc/get_and_add_deffered_credential.dart index 35bd0314b..8607f75cc 100644 --- a/lib/oidc4vc/get_and_add_deffered_credential.dart +++ b/lib/oidc4vc/get_and_add_deffered_credential.dart @@ -52,7 +52,7 @@ Future getAndAddDefferedCredential({ if (profileCubit.state.model.isDeveloperMode) { final value = await qrCodeScanCubit.showDataBeforeSending( - title: 'DEFERRED CREDENTIAL DATA', + title: 'DEFERRED CREDENTIAL REQUEST', data: body, ); diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 2f829e9bb..0eb854cc0 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -134,7 +134,7 @@ Future getAuthorizationUriForIssuer({ if (profileCubit.state.model.isDeveloperMode) { final value = await qrCodeScanCubit.showDataBeforeSending( - title: 'Pushed Authorization Request Data', + title: 'PUSHED AUTHORIZATION REQUEST', data: authorizationRequestParemeters, ); diff --git a/lib/oidc4vc/get_credential.dart b/lib/oidc4vc/get_credential.dart index ae26bc588..c9c1080ba 100644 --- a/lib/oidc4vc/get_credential.dart +++ b/lib/oidc4vc/get_credential.dart @@ -111,7 +111,7 @@ Future< if (profileCubit.state.model.isDeveloperMode) { final value = await qrCodeScanCubit.showDataBeforeSending( - title: 'CREDENTIAL DATA', + title: 'CREDENTIAL REQUEST', data: credentialData, ); @@ -167,7 +167,7 @@ Future< if (profileCubit.state.model.isDeveloperMode) { await qrCodeScanCubit.showDataBeforeSending( - title: 'CREDENTIAL DATA', + title: 'CREDENTIAL REQUEST', data: credentialData, ); diff --git a/lib/scan/cubit/scan_cubit.dart b/lib/scan/cubit/scan_cubit.dart index 385203526..06c4d0c81 100644 --- a/lib/scan/cubit/scan_cubit.dart +++ b/lib/scan/cubit/scan_cubit.dart @@ -620,7 +620,7 @@ class ScanCubit extends Cubit { if (profileCubit.state.model.isDeveloperMode) { final value = await qrCodeScanCubit.showDataBeforeSending( - title: 'Response Data', + title: 'RESPONSE REQUEST', data: body, ); if (value) { diff --git a/lib/splash/bloclisteners/blocklisteners.dart b/lib/splash/bloclisteners/blocklisteners.dart index 28f9219cc..836522d60 100644 --- a/lib/splash/bloclisteners/blocklisteners.dart +++ b/lib/splash/bloclisteners/blocklisteners.dart @@ -348,13 +348,20 @@ final qrCodeBlocListener = BlocListener( context: context, builder: (_) { return DeveloperModeDialog( - onDisplay: () { - Navigator.of(context).push( + onDisplay: () async { + final returnedValue = + await Navigator.of(context).push( JsonViewerPage.route( title: l10n.display, data: formattedData, ), ); + + if (returnedValue != null && + returnedValue is bool && + returnedValue) { + Navigator.of(context).pop(true); + } return; }, onDownload: () { @@ -555,13 +562,21 @@ final qrCodeBlocListener = BlocListener( context: context, builder: (_) { return DeveloperModeDialog( - onDisplay: () { - Navigator.of(context).push( + onDisplay: () async { + final returnedValue = + await Navigator.of(context).push( JsonViewerPage.route( title: l10n.display, data: data, ), ); + + if (returnedValue != null && + returnedValue is bool && + returnedValue) { + Navigator.of(context).pop(true); + } + return; }, onDownload: () { @@ -597,7 +612,6 @@ final qrCodeBlocListener = BlocListener( JsonViewerPage.route( title: l10n.display, data: data, - showContinueButton: true, ), );