From 744365b3257b02a5917014ffbcc02dc025e2f2a5 Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Thu, 19 Sep 2024 12:55:52 +0000 Subject: [PATCH 1/7] chores --- lib/app/shared/helper_functions/helper_functions.dart | 4 ++-- .../crypto_bottom_sheet/view/crypto_bottom_sheet_view.dart | 2 +- .../helper_functions/get_credential_manifest_from_altme.dart | 2 +- .../missing_creentials/cubit/missing_credentials_cubit.dart | 2 +- lib/matrix_notification/view/notification_page.dart | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 5b7d59a00..1678ffcdc 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -99,7 +99,7 @@ String getCredentialName(String constraints) { final dynamic constraintsJson = jsonDecode(constraints); final fieldsPath = JsonPath(r'$..fields'); final dynamic credentialField = - (fieldsPath.read(constraintsJson).first.value as List) + (fieldsPath.read(constraintsJson).first.value! as List) .where( (dynamic e) => e['path'].toString() == r'[$.credentialSubject.type]', @@ -113,7 +113,7 @@ String getIssuersName(String constraints) { final dynamic constraintsJson = jsonDecode(constraints); final fieldsPath = JsonPath(r'$..fields'); final dynamic issuerField = - (fieldsPath.read(constraintsJson).first.value as List) + (fieldsPath.read(constraintsJson).first.value! as List) .where( (dynamic e) => e['path'].toString() == r'[$.issuer]', ) diff --git a/lib/dashboard/crypto_account_switcher/crypto_bottom_sheet/view/crypto_bottom_sheet_view.dart b/lib/dashboard/crypto_account_switcher/crypto_bottom_sheet/view/crypto_bottom_sheet_view.dart index ed468a07d..2e01ca4b7 100644 --- a/lib/dashboard/crypto_account_switcher/crypto_bottom_sheet/view/crypto_bottom_sheet_view.dart +++ b/lib/dashboard/crypto_account_switcher/crypto_bottom_sheet/view/crypto_bottom_sheet_view.dart @@ -215,7 +215,7 @@ class _CryptoBottomSheetPageState extends State { ConfirmDialog( title: l10n .deleteAccountMessage( - data.name), + data.name,), yes: l10n.ok, showNoButton: false, ), diff --git a/lib/dashboard/home/tab_bar/credentials/helper_functions/get_credential_manifest_from_altme.dart b/lib/dashboard/home/tab_bar/credentials/helper_functions/get_credential_manifest_from_altme.dart index 12157492c..e794d7926 100644 --- a/lib/dashboard/home/tab_bar/credentials/helper_functions/get_credential_manifest_from_altme.dart +++ b/lib/dashboard/home/tab_bar/credentials/helper_functions/get_credential_manifest_from_altme.dart @@ -19,7 +19,7 @@ Future getCredentialManifestFromAltMe({ credentialManifetPath .read(jsonDecode(jsonEncode(openIdConfiguration))) .first - .value as Map, + .value! as Map, ); return credentialManifest; } diff --git a/lib/dashboard/missing_creentials/cubit/missing_credentials_cubit.dart b/lib/dashboard/missing_creentials/cubit/missing_credentials_cubit.dart index e9f632611..eb5e6dee1 100644 --- a/lib/dashboard/missing_creentials/cubit/missing_credentials_cubit.dart +++ b/lib/dashboard/missing_creentials/cubit/missing_credentials_cubit.dart @@ -46,7 +46,7 @@ class MissingCredentialsCubit extends Cubit { /// using JsonPath to find credential Name final dynamic json = jsonDecode(jsonEncode(descriptor.constraints)); final dynamic credentialField = - (JsonPath(r'$..fields').read(json).first.value as List) + (JsonPath(r'$..fields').read(json).first.value! as List) .toList() .first; diff --git a/lib/matrix_notification/view/notification_page.dart b/lib/matrix_notification/view/notification_page.dart index ccf67858c..0270137be 100644 --- a/lib/matrix_notification/view/notification_page.dart +++ b/lib/matrix_notification/view/notification_page.dart @@ -133,7 +133,7 @@ class _NotificationViewState children: [ Text( chatTimeFormatter( - message.createdAt ?? 0), + message.createdAt ?? 0,), style: TextStyle( color: colorScheme.onSurface, fontSize: 12, From 017727f94ec038029ba0d1fa65f75049a05eee0d Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Thu, 19 Sep 2024 13:48:14 +0000 Subject: [PATCH 2/7] Police of MY WALLET in bottom menu is too big o Android #2756 --- lib/theme/app_theme/app_theme.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/theme/app_theme/app_theme.dart b/lib/theme/app_theme/app_theme.dart index 6de658ea6..e6395760d 100644 --- a/lib/theme/app_theme/app_theme.dart +++ b/lib/theme/app_theme/app_theme.dart @@ -29,6 +29,9 @@ class AppTheme { fontSize: 20, fontWeight: FontWeight.normal, ), + bodySmall: TextStyle( + fontSize: 11, + ), ), buttonTheme: ButtonThemeData( textTheme: ButtonTextTheme.primary, From 39c29b912ce326dbf7ecc3b67a7be8962520a017 Mon Sep 17 00:00:00 2001 From: hawkbee <49282360+hawkbee1@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:43:56 +0200 Subject: [PATCH 3/7] October (#2906) * feat: Add switch to control notification #2869 * feat: Fix notification issue and make chat only custom * Update notification room #2875 * feat: Move notification menu to differnt place #2869 * refactor: Update notification switch location #2869 * Issue with name.firstname, cf slack #2880 * feat: Consider more constrainsts for presentation #2882 * feat: Consider more constrainsts for presentation #2882 * version update: 2.12.6+511 * Fix: All constraints considered #2882 and organise cred list alphabatically #2782 * feat: Improve vc details #2894 * refactor: Remove specified data #2894 * feat: Improve VC for SD-JWT with key binding data #2756 * feat: Remove jwt from json display in dev mode #2894 * feat: Add display log parameter #2895 * feat: Update wording for EBSI v3 #2896 * feat: Add new profile ebsi 4.0 #2897 * version update: 2.13.1+514 --------- Co-authored-by: Bibash Shrestha --- lib/app/shared/constants/parameters.dart | 1 + lib/app/shared/enum/type/oidc4vc_type.dart | 4 +- .../enum/type/profile/did_key_type.dart | 6 + .../enum/type/profile/profile_type.dart | 6 +- .../helper_functions/helper_functions.dart | 33 ++-- lib/app/shared/widget/wallet_logo.dart | 1 + .../widget/did_key_type_widget.dart | 1 + .../detail/widgets/developer_details.dart | 178 ++++++++++++++---- .../view/oid4c4vc_credential_pick_page.dart | 16 +- .../get_credentials_from_filter_list.dart | 27 ++- .../profile/cubit/profile_cubit.dart | 36 ++++ lib/dashboard/profile/models/profile.dart | 74 ++++++++ .../profile/models/profile_setting.dart | 5 + .../cubit/qr_code_scan_cubit.dart | 34 ++-- lib/l10n/arb/app_en.arb | 8 +- lib/l10n/untranslated.json | 24 ++- .../get_authorization_uri_for_issuer.dart | 4 +- lib/oidc4vc/get_credential.dart | 6 +- .../initiate_oidv4vc_credential_issuance.dart | 10 +- pubspec.yaml | 2 +- .../shared/enum/type/oidc4vc_type_test.dart | 2 +- .../helper_functions_test.dart | 14 +- 22 files changed, 387 insertions(+), 105 deletions(-) diff --git a/lib/app/shared/constants/parameters.dart b/lib/app/shared/constants/parameters.dart index 20a6eba73..219d25122 100644 --- a/lib/app/shared/constants/parameters.dart +++ b/lib/app/shared/constants/parameters.dart @@ -102,6 +102,7 @@ class Parameters { static const String walletName = 'altme_wallet'; static const DidKeyType didKeyTypeForEbsiV3 = DidKeyType.ebsiv3; + static const DidKeyType didKeyTypeForEbsiV4 = DidKeyType.ebsiv4; static const DidKeyType didKeyTypeForDefault = DidKeyType.edDSA; static const DidKeyType didKeyTypeForDutch = DidKeyType.jwkP256; static const DidKeyType didKeyTypeForOwfBaselineProfile = DidKeyType.jwkP256; diff --git a/lib/app/shared/enum/type/oidc4vc_type.dart b/lib/app/shared/enum/type/oidc4vc_type.dart index 5a1092b4d..f2bd80ab4 100644 --- a/lib/app/shared/enum/type/oidc4vc_type.dart +++ b/lib/app/shared/enum/type/oidc4vc_type.dart @@ -14,7 +14,7 @@ enum OIDC4VCType { presentationPrefix: 'openid-hedera://', ), - EBSIV3( + EBSI( offerPrefix: 'openid-credential-offer://', presentationPrefix: 'openid-vc://', ), @@ -44,7 +44,7 @@ extension OIDC4VCTypeX on OIDC4VCType { case OIDC4VCType.DEFAULT: case OIDC4VCType.GAIAX: case OIDC4VCType.GREENCYPHER: - case OIDC4VCType.EBSIV3: + case OIDC4VCType.EBSI: case OIDC4VCType.HAIP: return true; case OIDC4VCType.JWTVC: diff --git a/lib/app/shared/enum/type/profile/did_key_type.dart b/lib/app/shared/enum/type/profile/did_key_type.dart index 3502e31a9..91caedd7b 100644 --- a/lib/app/shared/enum/type/profile/did_key_type.dart +++ b/lib/app/shared/enum/type/profile/did_key_type.dart @@ -10,6 +10,7 @@ enum DidKeyType { p256, @JsonValue('did:key:ebsi') ebsiv3, + ebsiv4, @JsonValue('did:jwk:p-256') jwkP256, @JsonValue( @@ -29,6 +30,8 @@ extension DidKeyTypeX on DidKeyType { return 'did:key P-256'; case DidKeyType.ebsiv3: return 'did:key EBSI-V3'; + case DidKeyType.ebsiv4: + return 'did:key EBSI-V4'; case DidKeyType.jwkP256: return 'did:jwk P-256'; case DidKeyType.jwtClientAttestation: @@ -46,6 +49,8 @@ extension DidKeyTypeX on DidKeyType { return l10n.keyDecentralizedIDP256; case DidKeyType.ebsiv3: return l10n.ebsiV3DecentralizedId; + case DidKeyType.ebsiv4: + return l10n.ebsiV4DecentralizedId; case DidKeyType.jwkP256: return l10n.jwkDecentralizedIDP256; case DidKeyType.jwtClientAttestation: @@ -62,6 +67,7 @@ extension DidKeyTypeX on DidKeyType { case DidKeyType.edDSA: return true; case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: return false; } } diff --git a/lib/app/shared/enum/type/profile/profile_type.dart b/lib/app/shared/enum/type/profile/profile_type.dart index 21f239a49..0edf79370 100644 --- a/lib/app/shared/enum/type/profile/profile_type.dart +++ b/lib/app/shared/enum/type/profile/profile_type.dart @@ -1,6 +1,7 @@ enum ProfileType { defaultOne, ebsiV3, + ebsiV4, diipv2point1, diipv3, custom, @@ -13,7 +14,9 @@ extension ProfileTypeX on ProfileType { case ProfileType.custom: return 'Custom'; case ProfileType.ebsiV3: - return 'European Blockchain Services Infrastructure'; + return 'European Blockchain Services Infrastructure (EBSI v3.x)'; + case ProfileType.ebsiV4: + return 'European Blockchain Services Infrastructure (EBSI v4.x)'; case ProfileType.diipv2point1: return 'Decentralized Identity Interop Profile (DIIP v2.1)'; case ProfileType.enterprise: @@ -32,6 +35,7 @@ extension ProfileTypeX on ProfileType { case ProfileType.diipv2point1: return false; case ProfileType.ebsiV3: + case ProfileType.ebsiV4: case ProfileType.enterprise: case ProfileType.diipv3: return true; diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 1678ffcdc..4c5be8900 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -234,12 +234,12 @@ String getDateTimeWithoutSpace({DateTime? dateTime}) { } int getIndexValue({ - required bool isEBSIV3, + required bool isEBSI, required DidKeyType didKeyType, }) { switch (didKeyType) { case DidKeyType.secp256k1: - if (isEBSIV3) { + if (isEBSI) { return 3; } else { return 1; @@ -250,7 +250,8 @@ int getIndexValue({ return 5; case DidKeyType.jwkP256: return 6; - + case DidKeyType.ebsiv4: + return 7; case DidKeyType.edDSA: case DidKeyType.jwtClientAttestation: return 0; // it is not needed, just assigned @@ -282,7 +283,7 @@ Future getPrivateKey({ case DidKeyType.secp256k1: final index = getIndexValue( - isEBSIV3: true, + isEBSI: true, didKeyType: didKeyType, ); final key = profileCubit.oidc4vc.privateKeyFromMnemonic( @@ -293,9 +294,10 @@ Future getPrivateKey({ case DidKeyType.p256: case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: case DidKeyType.jwkP256: final indexValue = getIndexValue( - isEBSIV3: false, + isEBSI: false, didKeyType: didKeyType, ); @@ -398,9 +400,9 @@ DidKeyType? getDidKeyFromString(String? didKeyTypeString) { Future fetchPrivateKey({ required ProfileCubit profileCubit, required DidKeyType didKeyType, - bool? isEBSIV3, + bool? isEBSI, }) async { - if (isEBSIV3 != null && isEBSIV3) { + if (isEBSI != null && isEBSI) { final privateKey = await getPrivateKey( profileCubit: profileCubit, didKeyType: DidKeyType.ebsiv3, @@ -533,6 +535,7 @@ Future<(String, String)> getDidAndKid({ switch (didKeyType) { case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: //b'\xd1\xd6\x03' in python final List prefixByteList = [0xd1, 0xd6, 0x03]; @@ -592,11 +595,11 @@ Future<(String, String)> getDidAndKid({ Future<(String, String)> fetchDidAndKid({ required String privateKey, - bool? isEBSIV3, + bool? isEBSI, required ProfileCubit profileCubit, required DidKeyType didKeyType, }) async { - if (isEBSIV3 != null && isEBSIV3) { + if (isEBSI != null && isEBSI) { final (did, kid) = await getDidAndKid( didKeyType: DidKeyType.ebsiv3, privateKey: privateKey, @@ -785,7 +788,7 @@ Future< for (final oidc4vcType in OIDC4VCType.values) { if (oidc4vcType.isEnabled && url.startsWith(oidc4vcType.offerPrefix)) { if (oidc4vcType == OIDC4VCType.DEFAULT || - oidc4vcType == OIDC4VCType.EBSIV3) { + oidc4vcType == OIDC4VCType.EBSI) { if (credSupported?.trustFramework != null && credSupported == credSupported?.trustFramework) { return ( @@ -801,7 +804,7 @@ Future< if (credSupported?.trustFramework?.name != null && credSupported?.trustFramework?.name == 'ebsi') { return ( - OIDC4VCType.EBSIV3, + OIDC4VCType.EBSI, openIdConfiguration, authorizationServerConfiguration, credentialOfferJson, @@ -997,7 +1000,7 @@ Future?> getClientMetada({ } } -Future isEBSIV3ForVerifiers({ +Future isEBSIForVerifiers({ required Uri uri, required OIDC4VC oidc4vc, required OIDC4VCIDraftType oidc4vciDraftType, @@ -1595,7 +1598,7 @@ bool supportCryptoCredential(ProfileModel profileModel) { // oAuthClientAttestationPop Future<(String?, String?, String?, String?, String?)> getClientDetails({ required ProfileCubit profileCubit, - required bool isEBSIV3, + required bool isEBSI, required String issuer, }) async { try { @@ -1612,13 +1615,13 @@ Future<(String?, String?, String?, String?, String?)> getClientDetails({ final String privateKey = await fetchPrivateKey( profileCubit: profileCubit, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKeyType: didKeyType, ); final (did, _) = await fetchDidAndKid( privateKey: privateKey, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, profileCubit: profileCubit, didKeyType: didKeyType, ); diff --git a/lib/app/shared/widget/wallet_logo.dart b/lib/app/shared/widget/wallet_logo.dart index 0b5f4dbbe..58a429f2f 100644 --- a/lib/app/shared/widget/wallet_logo.dart +++ b/lib/app/shared/widget/wallet_logo.dart @@ -33,6 +33,7 @@ class WalletLogo extends StatelessWidget { ? ImageStrings.appLogoStage : ImageStrings.appLogo; case ProfileType.ebsiV3: + case ProfileType.ebsiV4: image = ImageStrings.ebsiLogo; case ProfileType.enterprise: final isLightTheme = diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart index 5c2012174..1b453c4df 100644 --- a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart @@ -40,6 +40,7 @@ class DidKeyTypeWidget extends StatelessWidget { VCFormatType.ldpVc; final isUnmatchedDid = didKeyType == DidKeyType.ebsiv3 || + didKeyType == DidKeyType.ebsiv4 || didKeyType == DidKeyType.jwkP256; if (isldpVc && isUnmatchedDid) { diff --git a/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart b/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart index 6c054deb2..ba634e3c3 100644 --- a/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart +++ b/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart @@ -1,7 +1,12 @@ +import 'dart:convert'; + import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; import 'package:altme/l10n/l10n.dart'; +import 'package:altme/selective_disclosure/selective_disclosure.dart'; import 'package:flutter/material.dart'; +import 'package:jwt_decode/jwt_decode.dart'; +import 'package:oidc4vc/oidc4vc.dart'; class DeveloperDetails extends StatelessWidget { const DeveloperDetails({ @@ -21,14 +26,74 @@ class DeveloperDetails extends StatelessWidget { Widget build(BuildContext context) { final l10n = context.l10n; - final String issuerDid = credentialModel.credentialPreview.issuer; - final String subjectDid = - credentialModel.credentialPreview.credentialSubjectModel.id ?? ''; - final String type = credentialModel.credentialPreview.type.toString(); + // final String issuerDid = credentialModel.credentialPreview.issuer; + // final String subjectDid = + // credentialModel.credentialPreview.credentialSubjectModel.id ?? ''; + // final String type = credentialModel.credentialPreview.type.toString(); final titleColor = Theme.of(context).colorScheme.onSurface; final valueColor = Theme.of(context).colorScheme.onSurface; + final jwtDecode = JWTDecode(); + + String? header; + String? payload; + String? data; + + String? kbHeader; + String? kbPayload; + + if (credentialModel.jwt != null) { + final jsonheader = decodeHeader( + jwtDecode: jwtDecode, + token: credentialModel.jwt!, + ); + header = const JsonEncoder.withIndent(' ').convert(jsonheader); + final jsonPayload = decodePayload( + jwtDecode: jwtDecode, + token: credentialModel.jwt!, + ); + payload = const JsonEncoder.withIndent(' ').convert( + Map.of(jsonPayload)..removeWhere((key, value) => key == 'jwt'), + ); + + if (credentialModel.getFormat == VCFormatType.vcSdJWT.vcValue) { + final selectiveDisclosure = SelectiveDisclosure(credentialModel); + + final data = createJsonByDecryptingSDValues( + encryptedJson: credentialModel.data, + selectiveDisclosure: selectiveDisclosure, + ); + + payload = const JsonEncoder.withIndent(' ') + .convert(Map.of(data)..removeWhere((key, value) => key == 'jwt')); + + final probableJwt = credentialModel.jwt?.split('~').last; + kbHeader = 'None'; + kbPayload = 'None'; + + if (probableJwt != null && + probableJwt.isNotEmpty && + probableJwt.startsWith('e')) { + try { + final header = jwtDecode.parseJwtHeader(probableJwt); + kbHeader = const JsonEncoder.withIndent(' ').convert(header); + } catch (e) { + kbHeader = 'None'; + } + + try { + final payload = jwtDecode.parseJwt(probableJwt); + kbPayload = const JsonEncoder.withIndent(' ').convert(payload); + } catch (e) { + kbPayload = 'None'; + } + } + } + } else { + data = const JsonEncoder.withIndent(' ').convert(credentialModel.data); + } + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -40,53 +105,96 @@ class DeveloperDetails extends StatelessWidget { valueColor: valueColor, showVertically: showVertically, ), - CredentialField( - padding: const EdgeInsets.only(top: 10), - title: l10n.issuerDID, - value: issuerDid, - titleColor: titleColor, - valueColor: valueColor, - showVertically: showVertically, - ), - if (credentialModel.credentialPreview.credentialSubjectModel - is! WalletCredentialModel && - subjectDid.isNotEmpty) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.issuerDID, + // value: issuerDid, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // if (credentialModel.credentialPreview.credentialSubjectModel + // is! WalletCredentialModel && + // subjectDid.isNotEmpty) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.subjectDID, + // value: subjectDid, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.type, + // value: type, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // if (statusListUri != null) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.statusList, + // value: statusListUri.toString(), + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: false, + // ), + // if (statusListIndex != null) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.statusListIndex, + // value: statusListIndex.toString(), + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: false, + // ), + if (header != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.subjectDID, - value: subjectDid, + title: l10n.header, + value: header, titleColor: titleColor, valueColor: valueColor, showVertically: showVertically, ), - CredentialField( - padding: const EdgeInsets.only(top: 10), - title: l10n.type, - value: type, - titleColor: titleColor, - valueColor: valueColor, - showVertically: showVertically, - ), - if (statusListUri != null) ...[ + if (payload != null) + CredentialField( + padding: const EdgeInsets.only(top: 10), + title: l10n.payload, + value: payload, + titleColor: titleColor, + valueColor: valueColor, + showVertically: showVertically, + ), + if (data != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.statusList, - value: statusListUri.toString(), + title: l10n.data, + value: data, titleColor: titleColor, valueColor: valueColor, - showVertically: false, + showVertically: showVertically, ), - ], - if (statusListIndex != null) ...[ + if (kbHeader != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.statusListIndex, - value: statusListIndex.toString(), + title: l10n.keyBindingHeader, + value: kbHeader, titleColor: titleColor, valueColor: valueColor, - showVertically: false, + showVertically: showVertically, + ), + if (kbPayload != null) + CredentialField( + padding: const EdgeInsets.only(top: 10), + title: l10n.keyBindingPayload, + value: kbPayload, + titleColor: titleColor, + valueColor: valueColor, + showVertically: showVertically, ), - ], ], ); } 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 63685d8ca..1aba69219 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 @@ -13,7 +13,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { required this.userPin, required this.preAuthorizedCode, required this.issuer, - required this.isEBSIV3, + required this.isEBSI, required this.credentialOfferJson, required this.openIdConfiguration, }); @@ -22,7 +22,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { final String? userPin; final String? preAuthorizedCode; final String issuer; - final bool isEBSIV3; + final bool isEBSI; final dynamic credentialOfferJson; final OpenIdConfiguration openIdConfiguration; @@ -31,7 +31,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { required String? userPin, required String? preAuthorizedCode, required String issuer, - required bool isEBSIV3, + required bool isEBSI, required dynamic credentialOfferJson, required OpenIdConfiguration openIdConfiguration, }) => @@ -41,7 +41,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -57,7 +57,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -72,7 +72,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { required this.userPin, required this.preAuthorizedCode, required this.issuer, - required this.isEBSIV3, + required this.isEBSI, required this.credentialOfferJson, required this.openIdConfiguration, }); @@ -81,7 +81,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { final String? userPin; final String? preAuthorizedCode; final String issuer; - final bool isEBSIV3; + final bool isEBSI; final dynamic credentialOfferJson; final OpenIdConfiguration openIdConfiguration; @@ -198,7 +198,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, qrCodeScanCubit: context.read(), diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart index 95cafaac7..e1649273f 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart @@ -13,8 +13,10 @@ List getCredentialsFromFilterList({ /// remove ldp_vp if jwt_vp is required final selectedCredential = []; - for (final field in filterList) { - for (final credential in credentialList) { + + for (final credential in credentialList) { + fieldLoop: + for (final field in filterList) { for (final path in field.path) { final credentialData = createJsonByDecryptingSDValues( encryptedJson: credential.data, @@ -63,12 +65,29 @@ List getCredentialsFromFilterList({ if (searchList.isNotEmpty) { selectedCredential.add(credential); } else { - break; + break fieldLoop; } } } } - return selectedCredential.toSet().toList(); + + final credentials = selectedCredential.toSet().toList(); + + credentials.sort( + (a, b) { + final firstCredName = a.display?.name ?? + a.credentialPreview.credentialSubjectModel.credentialSubjectType + .name; + final secondCredName = b.display?.name ?? + b.credentialPreview.credentialSubjectModel.credentialSubjectType + .name; + + return firstCredName.compareTo(secondCredName); + }, + ); + + return credentials; } + return credentialList; } diff --git a/lib/dashboard/profile/cubit/profile_cubit.dart b/lib/dashboard/profile/cubit/profile_cubit.dart index 048ee8332..d0452efe8 100644 --- a/lib/dashboard/profile/cubit/profile_cubit.dart +++ b/lib/dashboard/profile/cubit/profile_cubit.dart @@ -237,6 +237,28 @@ class ProfileCubit extends Cubit { enterpriseWalletName: enterpriseWalletName, ); + case ProfileType.ebsiV4: + final privateKey = await getPrivateKey( + didKeyType: Parameters.didKeyTypeForEbsiV4, + profileCubit: this, + ); + + final (did, _) = await getDidAndKid( + didKeyType: Parameters.didKeyTypeForEbsiV4, + privateKey: privateKey, + profileCubit: this, + ); + + profileModel = ProfileModel.ebsiV4( + polygonIdNetwork: polygonIdNetwork, + walletType: walletType, + walletProtectionType: walletProtectionType, + isDeveloperMode: isDeveloperMode, + clientId: did, + clientSecret: randomString(12), + enterpriseWalletName: enterpriseWalletName, + ); + case ProfileType.diipv2point1: final privateKey = await getPrivateKey( didKeyType: Parameters.didKeyTypeForDutch, @@ -599,6 +621,20 @@ class ProfileCubit extends Cubit { .selfSovereignIdentityOptions.customOidc4vcProfile.clientSecret, ), ); + case ProfileType.ebsiV4: + await update( + ProfileModel.ebsiV4( + polygonIdNetwork: state.model.polygonIdNetwork, + walletProtectionType: state.model.walletProtectionType, + isDeveloperMode: state.model.isDeveloperMode, + walletType: state.model.walletType, + enterpriseWalletName: state.model.enterpriseWalletName, + clientId: state.model.profileSetting.selfSovereignIdentityOptions + .customOidc4vcProfile.clientId, + clientSecret: state.model.profileSetting + .selfSovereignIdentityOptions.customOidc4vcProfile.clientSecret, + ), + ); case ProfileType.defaultOne: await update( ProfileModel.defaultOne( diff --git a/lib/dashboard/profile/models/profile.dart b/lib/dashboard/profile/models/profile.dart index deeb2ccff..f31c5309a 100644 --- a/lib/dashboard/profile/models/profile.dart +++ b/lib/dashboard/profile/models/profile.dart @@ -104,6 +104,80 @@ class ProfileModel extends Equatable { ), ); + factory ProfileModel.ebsiV4({ + required PolygonIdNetwork polygonIdNetwork, + required WalletType walletType, + required WalletProtectionType walletProtectionType, + required bool isDeveloperMode, + required String? clientId, + required String? clientSecret, + String? enterpriseWalletName, + }) => + ProfileModel( + enterpriseWalletName: enterpriseWalletName, + polygonIdNetwork: polygonIdNetwork, + walletType: walletType, + walletProtectionType: walletProtectionType, + isDeveloperMode: isDeveloperMode, + profileType: ProfileType.ebsiV4, + profileSetting: ProfileSetting( + blockchainOptions: BlockchainOptions.initial(), + generalOptions: GeneralOptions.empty(), + helpCenterOptions: HelpCenterOptions.initial(), + discoverCardsOptions: const DiscoverCardsOptions( + displayDefi: false, + displayHumanity: false, + displayHumanityJwt: false, + displayOver13: false, + displayOver15: false, + displayOver18: false, + displayOver18Jwt: false, + displayOver21: false, + displayOver50: false, + displayChainborn: false, + displayTezotopia: false, + displayVerifiableId: false, + displayVerifiableIdJwt: true, + displayOver65: false, + displayEmailPass: false, + displayEmailPassJwt: false, + displayPhonePass: false, + displayPhonePassJwt: false, + displayAgeRange: false, + displayGender: false, + displayExternalIssuer: [], + ), + selfSovereignIdentityOptions: SelfSovereignIdentityOptions( + displayManageDecentralizedId: true, + customOidc4vcProfile: CustomOidc4VcProfile( + clientAuthentication: ClientAuthentication.clientId, + credentialManifestSupport: false, + cryptoHolderBinding: true, + defaultDid: Parameters.didKeyTypeForEbsiV3, + oidc4vciDraft: OIDC4VCIDraftType.draft13, + oidc4vpDraft: OIDC4VPDraftType.draft10, + scope: false, + securityLevel: true, + proofHeader: ProofHeaderType.kid, + siopv2Draft: SIOPV2DraftType.draft12, + clientType: ClientType.did, + clientId: clientId, + clientSecret: clientSecret, + vcFormatType: VCFormatType.auto, + proofType: ProofType.jwt, + ), + ), + settingsMenu: SettingsMenu.initial(), + version: '', + walletSecurityOptions: const WalletSecurityOptions( + confirmSecurityVerifierAccess: true, + displaySecurityAdvancedSettings: true, + secureSecurityAuthenticationWithPinCode: true, + verifySecurityIssuerWebsiteIdentity: true, + ), + ), + ); + factory ProfileModel.defaultOne({ required PolygonIdNetwork polygonIdNetwork, required WalletType walletType, diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index 5cf6b002c..7f6812f88 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -739,6 +739,7 @@ class SettingsMenu extends Equatable { required this.displayHelpCenter, required this.displayProfile, this.displaySelfSovereignIdentity = true, + this.displayActivityLog = false, }); factory SettingsMenu.fromJson(Map json) => @@ -754,6 +755,7 @@ class SettingsMenu extends Equatable { final bool displayHelpCenter; final bool displayProfile; final bool displaySelfSovereignIdentity; + final bool displayActivityLog; Map toJson() => _$SettingsMenuToJson(this); @@ -762,6 +764,7 @@ class SettingsMenu extends Equatable { bool? displayHelpCenter, bool? displayProfile, bool? displaySelfSovereignIdentity, + bool? displayActivityLog, }) => SettingsMenu( displayDeveloperMode: displayDeveloperMode ?? this.displayDeveloperMode, @@ -769,6 +772,7 @@ class SettingsMenu extends Equatable { displayProfile: displayProfile ?? this.displayProfile, displaySelfSovereignIdentity: displaySelfSovereignIdentity ?? this.displaySelfSovereignIdentity, + displayActivityLog: displayActivityLog ?? this.displayActivityLog, ); @override @@ -777,6 +781,7 @@ class SettingsMenu extends Equatable { displayHelpCenter, displayProfile, displaySelfSovereignIdentity, + displayActivityLog, ]; } 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 4634e0b96..fd2ebd1de 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 @@ -246,7 +246,7 @@ class QRCodeScanCubit extends Cubit { await startOIDC4VCCredentialIssuance( scannedResponse: uri.toString(), - isEBSIV3: oidcType == OIDC4VCType.EBSIV3, + isEBSI: oidcType == OIDC4VCType.EBSI, qrCodeScanCubit: qrCodeScanCubit, oidc4vciDraftType: customOidc4vcProfile.oidc4vciDraft, credentialOfferJson: credentialOfferJson, @@ -456,7 +456,7 @@ class QRCodeScanCubit extends Cubit { Future startOIDC4VCCredentialIssuance({ required String scannedResponse, - required bool isEBSIV3, + required bool isEBSI, required QRCodeScanCubit qrCodeScanCubit, required OIDC4VCIDraftType oidc4vciDraftType, required dynamic credentialOfferJson, @@ -533,7 +533,7 @@ class QRCodeScanCubit extends Cubit { dioClient: client, userPin: userPin, oidc4vc: oidc4vc, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, @@ -562,7 +562,7 @@ class QRCodeScanCubit extends Cubit { dioClient: client, userPin: null, credentialOfferJson: credentialOfferJson, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, oidc4vciDraftType: oidc4vciDraftType, profileCubit: profileCubit, @@ -890,7 +890,7 @@ class QRCodeScanCubit extends Cubit { required String? userPin, required String? preAuthorizedCode, required String issuer, - required bool isEBSIV3, + required bool isEBSI, required dynamic credentialOfferJson, required OpenIdConfiguration openIdConfiguration, }) { @@ -902,7 +902,7 @@ class QRCodeScanCubit extends Cubit { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -1189,8 +1189,8 @@ class QRCodeScanCubit extends Cubit { final nonce = state.uri?.queryParameters['nonce']; final stateValue = state.uri?.queryParameters['state']; - // final bool? isEBSIV3 = - // await isEBSIV3ForVerifier(client: client, uri: state.uri!); + // final bool? isEBSI = + // await isEBSIForVerifier(client: client, uri: state.uri!); final didKeyType = profileCubit.state.model.profileSetting .selfSovereignIdentityOptions.customOidc4vcProfile.defaultDid; @@ -1257,7 +1257,7 @@ class QRCodeScanCubit extends Cubit { Future processSelectedCredentials({ required List selectedCredentials, - required bool isEBSIV3, + required bool isEBSI, required String? userPin, required String? preAuthorizedCode, required String issuer, @@ -1273,7 +1273,7 @@ class QRCodeScanCubit extends Cubit { oAuthClientAttestationPop ) = await getClientDetails( profileCubit: profileCubit, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, issuer: issuer, ); @@ -1283,7 +1283,7 @@ class QRCodeScanCubit extends Cubit { if (preAuthorizedCode != null) { await addCredentialsInLoop( selectedCredentials: selectedCredentials, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, userPin: userPin, preAuthorizedCode: preAuthorizedCode, issuer: issuer, @@ -1303,7 +1303,7 @@ class QRCodeScanCubit extends Cubit { await getAuthorizationUriForIssuer( scannedResponse: state.uri.toString(), oidc4vc: oidc4vc, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKitProvider: didKitProvider, selectedCredentials: selectedCredentials, credentialOfferJson: credentialOfferJson, @@ -1333,7 +1333,7 @@ class QRCodeScanCubit extends Cubit { Future addCredentialsInLoop({ required List selectedCredentials, - required bool isEBSIV3, + required bool isEBSI, required String? userPin, required String? preAuthorizedCode, required String issuer, @@ -1437,7 +1437,7 @@ class QRCodeScanCubit extends Cubit { String? deferredCredentialEndpoint, String format, ) = await getCredential( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credential: selectedCredentials[i], issuer: issuer, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, @@ -1558,7 +1558,7 @@ class QRCodeScanCubit extends Cubit { final containsAllRequiredKey = statePayload.containsKey('credentials') && statePayload.containsKey('codeVerifier') && statePayload.containsKey('issuer') && - statePayload.containsKey('isEBSIV3'); + statePayload.containsKey('isEBSI'); if (!containsAllRequiredKey) { throw ResponseMessage( @@ -1572,7 +1572,7 @@ class QRCodeScanCubit extends Cubit { final selectedCredentials = statePayload['credentials'] as List; final String codeVerifier = statePayload['codeVerifier'].toString(); final String issuer = statePayload['issuer'].toString(); - final bool isEBSIV3 = statePayload['isEBSIV3'] as bool; + final bool isEBSI = statePayload['isEBSI'] as bool; final String? authorization = statePayload['authorization'] as String?; final String? clientId = statePayload['client_id'] as String?; final String? clientSecret = statePayload['client_secret'] as String?; @@ -1586,7 +1586,7 @@ class QRCodeScanCubit extends Cubit { userPin: null, issuer: issuer, preAuthorizedCode: null, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, codeForAuthorisedFlow: codeForAuthorisedFlow, codeVerifier: codeVerifier, authorization: authorization, diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index b65902088..1c2c0348b 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -1068,5 +1068,11 @@ "notificationTitle": "Welcome to the Notifications!\nStay informed with important updates.", "chatRoom": "Chat room", "notificationRoom": "Notification room", - "notificationSubtitle": "Enable to get the notification" + "notificationSubtitle": "Enable to get the notification", + "header": "Header", + "payload": "Payload", + "data": "Data", + "keyBindingHeader": "Key Binding Header", + "keyBindingPayload": "Key Binding Payload", + "ebsiV4DecentralizedId": "did:key EBSI V4 P-256" } diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 1c5340d34..8784f590f 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -38,7 +38,13 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ], "es": [ @@ -80,7 +86,13 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ], "fr": [ @@ -127,6 +139,12 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ] } diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 5f96a54d2..53cc33ccf 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -11,7 +11,7 @@ import 'package:uuid/uuid.dart'; Future getAuthorizationUriForIssuer({ required String scannedResponse, required OIDC4VC oidc4vc, - required bool isEBSIV3, + required bool isEBSI, required DIDKitProvider didKitProvider, required List selectedCredentials, required String issuer, @@ -49,7 +49,7 @@ Future getAuthorizationUriForIssuer({ 'codeVerifier': pkcePair.codeVerifier, 'credentials': selectedCredentials, 'issuer': issuer, - 'isEBSIV3': isEBSIV3, + 'isEBSI': isEBSI, }; switch (clientAuthentication) { diff --git a/lib/oidc4vc/get_credential.dart b/lib/oidc4vc/get_credential.dart index cdb0dbb1f..921577078 100644 --- a/lib/oidc4vc/get_credential.dart +++ b/lib/oidc4vc/get_credential.dart @@ -12,7 +12,7 @@ Future< String?, String, )> getCredential({ - required bool isEBSIV3, + required bool isEBSI, required dynamic credential, required ProfileCubit profileCubit, required String issuer, @@ -26,13 +26,13 @@ Future< required List? authorizationDetails, }) async { final privateKey = await fetchPrivateKey( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKeyType: didKeyType, profileCubit: profileCubit, ); final (did, kid) = await fetchDidAndKid( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, privateKey: privateKey, didKeyType: didKeyType, profileCubit: profileCubit, diff --git a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart index aa62d62ac..724703770 100644 --- a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart +++ b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart @@ -11,7 +11,7 @@ import 'package:secure_storage/secure_storage.dart'; Future initiateOIDC4VCCredentialIssuance({ required String scannedResponse, required OIDC4VC oidc4vc, - required bool isEBSIV3, + required bool isEBSI, required QRCodeScanCubit qrCodeScanCubit, required DIDKitProvider didKitProvider, required CredentialsCubit credentialsCubit, @@ -88,7 +88,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ); @@ -100,7 +100,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ); @@ -131,7 +131,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: null, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, codeForAuthorisedFlow: codeForAuthorisedFlow, codeVerifier: codeVerifier, authorization: authorization, @@ -149,7 +149,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, selectedCredentials: [credentials], qrCodeScanCubit: qrCodeScanCubit, diff --git a/pubspec.yaml b/pubspec.yaml index 80b2053b2..f61e163f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.13.0+513 +version: 2.13.1+514 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: diff --git a/test/app/shared/enum/type/oidc4vc_type_test.dart b/test/app/shared/enum/type/oidc4vc_type_test.dart index 0cde1154c..d27977282 100644 --- a/test/app/shared/enum/type/oidc4vc_type_test.dart +++ b/test/app/shared/enum/type/oidc4vc_type_test.dart @@ -7,7 +7,7 @@ void main() { expect(OIDC4VCType.DEFAULT.isEnabled, equals(true)); expect(OIDC4VCType.GAIAX.isEnabled, equals(true)); expect(OIDC4VCType.GREENCYPHER.isEnabled, equals(true)); - expect(OIDC4VCType.EBSIV3.isEnabled, equals(true)); + expect(OIDC4VCType.EBSI.isEnabled, equals(true)); expect(OIDC4VCType.JWTVC.isEnabled, equals(false)); expect(OIDC4VCType.HAIP.isEnabled, equals(true)); }); diff --git a/test/app/shared/helper_functions/helper_functions_test.dart b/test/app/shared/helper_functions/helper_functions_test.dart index 89bed8bd4..fd1933e03 100644 --- a/test/app/shared/helper_functions/helper_functions_test.dart +++ b/test/app/shared/helper_functions/helper_functions_test.dart @@ -232,21 +232,21 @@ void main() { test('getIndexValue returns correct index for each DidKeyType', () { expect( - getIndexValue(isEBSIV3: true, didKeyType: DidKeyType.secp256k1), + getIndexValue(isEBSI: true, didKeyType: DidKeyType.secp256k1), 3, ); expect( - getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.secp256k1), + getIndexValue(isEBSI: false, didKeyType: DidKeyType.secp256k1), 1, ); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.p256), 4); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.ebsiv3), 5); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.jwkP256), 6); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.edDSA), 0); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.p256), 4); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.ebsiv3), 5); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.jwkP256), 6); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.edDSA), 0); expect( getIndexValue( - isEBSIV3: false, + isEBSI: false, didKeyType: DidKeyType.jwtClientAttestation, ), 0, From 61262a9bc882e9be205732fd2931843d9df4217d Mon Sep 17 00:00:00 2001 From: hawkbee <49282360+hawkbee1@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:12:17 +0200 Subject: [PATCH 4/7] Disclosable child of undisclosable (#2910) * get a display * deal properly with json value inside selective disclosure which has a claim * Issuer metadata / display / type as "uri" to display as a link in the wallet #2907 --- .../shared/widget/base/credential_field.dart | 22 +++++++++++- .../selective_disclosure_display_map.dart | 35 +++++++++++++++---- .../selective_disclosure.dart | 2 +- .../widget/display_selective_disclosure.dart | 1 + pubspec.lock | 12 +++---- 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/lib/app/shared/widget/base/credential_field.dart b/lib/app/shared/widget/base/credential_field.dart index 72d0e63d5..fb7116f31 100644 --- a/lib/app/shared/widget/base/credential_field.dart +++ b/lib/app/shared/widget/base/credential_field.dart @@ -1,3 +1,5 @@ +import 'package:altme/app/shared/launch_url/launch_url.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; class CredentialField extends StatelessWidget { @@ -9,6 +11,7 @@ class CredentialField extends StatelessWidget { this.titleColor, this.valueColor, this.padding = const EdgeInsets.all(8), + this.type = 'string', }); final String value; @@ -17,6 +20,7 @@ class CredentialField extends StatelessWidget { final Color? valueColor; final EdgeInsetsGeometry padding; final bool showVertically; + final String type; @override Widget build(BuildContext context) { @@ -29,6 +33,7 @@ class CredentialField extends StatelessWidget { valueColor: valueColor, padding: padding, showVertically: showVertically, + type: type, ), ); } @@ -43,6 +48,7 @@ class DisplayCredentialField extends StatelessWidget { this.valueColor, required this.padding, required this.showVertically, + this.type = 'string', }); final String? title; @@ -51,6 +57,7 @@ class DisplayCredentialField extends StatelessWidget { final Color? valueColor; final EdgeInsetsGeometry padding; final bool showVertically; + final String type; @override Widget build(BuildContext context) { @@ -74,7 +81,20 @@ class DisplayCredentialField extends StatelessWidget { ], TextSpan( text: value, - style: textTheme.bodyMedium!.copyWith(color: valueColor), + style: textTheme.bodyMedium!.copyWith( + color: (type == 'uri' || type == 'email') + ? Theme.of(context).colorScheme.primary + : valueColor, + ), + recognizer: TapGestureRecognizer() + ..onTap = () async { + if (type == 'uri') { + await LaunchUrl.launch(value); + } + if (type == 'email') { + await LaunchUrl.launch('mailto:$value'); + } + }, ), ], ), diff --git a/lib/selective_disclosure/helper_functions/selective_disclosure_display_map.dart b/lib/selective_disclosure/helper_functions/selective_disclosure_display_map.dart index 90dcce9c2..00e9600c1 100644 --- a/lib/selective_disclosure/helper_functions/selective_disclosure_display_map.dart +++ b/lib/selective_disclosure/helper_functions/selective_disclosure_display_map.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:altme/app/shared/extension/iterable_extension.dart'; import 'package:altme/dashboard/home/tab_bar/credentials/models/credential_model/credential_model.dart'; import 'package:altme/dashboard/home/tab_bar/credentials/present/pick/selective_disclosure/cubit/selective_disclosure_pick_cubit.dart'; @@ -46,7 +48,8 @@ class SelectiveDisclosureDisplayMap { if (display == null) return; title = display['name'].toString(); - + /// Getting value_type if defined in the claim + final type = mapValue['value_type'] as String?; final bool hasNestedData = mapValue.values.any((element) => element is Map); @@ -65,9 +68,13 @@ class SelectiveDisclosureDisplayMap { ).buildMap; if (nestedMap.isNotEmpty) { builtMap[title] = nestedMap; + } else { + builtMap.addAll( + claimData(mapKey, title, type), + ); } } else { - builtMap.addAll(claimData(mapKey, title)); + builtMap.addAll(claimData(mapKey, title, type)); } }); final Map mapFromJwtEntries = fileterdMapFromJwt( @@ -147,7 +154,7 @@ class SelectiveDisclosureDisplayMap { if (!currentClaims.containsKey(element.key) || currentClaims[element.key].length == 0) { if (element.value is Map) { - builtMap.addAll(MapForNestedClaimWithoutDisplay(element)); + builtMap.addAll(MapForNestedClaimWithoutDisplay(element, null)); continue; } @@ -155,6 +162,7 @@ class SelectiveDisclosureDisplayMap { claimData( element.key.toString(), element.key.toString(), + null, ), ); } @@ -165,6 +173,7 @@ class SelectiveDisclosureDisplayMap { /// can be used in recursive way to get more nested levels Map MapForNestedClaimWithoutDisplay( dynamic element, + String? title, ) { final value = element.value as Map; final builtMap = {}; @@ -199,7 +208,7 @@ class SelectiveDisclosureDisplayMap { (entry) => entry.value.toString().contains(element.key.toString()), ); if (index == -1) isDisabled = true; - builtMap[element.key.toString()] = { + builtMap[title ?? element.key.toString()] = { 'mapKey': element.key.toString(), 'claimKey': element.key.toString(), 'threeDotValue': null, @@ -212,7 +221,11 @@ class SelectiveDisclosureDisplayMap { return builtMap; } - Map claimData(String mapKey, String? title) { + Map claimData( + String mapKey, + String? title, + String? type, + ) { final claimDataMap = {}; final List claimsData = SelectiveDisclosure(credentialModel).getClaimsData( @@ -280,14 +293,22 @@ class SelectiveDisclosureDisplayMap { (entry) => entry.value.toString().contains(claimKey), ); if (indexInDisclosure == -1) isDisabled = true; - + // ignore: inference_failure_on_uninitialized_variable, prefer_typing_uninitialized_variables + late final value; + try { + final json = jsonDecode(element.data); + value = json; + } catch (e) { + value = element.data; + } final listElement = { 'mapKey': mapKey, 'claimKey': claimKey, 'threeDotValue': element.threeDotValue, - 'value': element.data, + 'value': value, 'hasCheckbox': !isDisabled && isPresentation, 'isCompulsary': isCompulsary, + 'type': type, }; if (claimsData.length > 1) { if (index == 0) { diff --git a/lib/selective_disclosure/selective_disclosure.dart b/lib/selective_disclosure/selective_disclosure.dart index f76a591db..02b2ca82d 100644 --- a/lib/selective_disclosure/selective_disclosure.dart +++ b/lib/selective_disclosure/selective_disclosure.dart @@ -211,7 +211,7 @@ class SelectiveDisclosure { value.add( ClaimsData( isfromDisclosureOfJWT: true, - data: data.toString(), + data: data is Map ? jsonEncode(data) : data.toString(), ), ); } catch (e) { diff --git a/lib/selective_disclosure/widget/display_selective_disclosure.dart b/lib/selective_disclosure/widget/display_selective_disclosure.dart index d2cc5c087..172b5246f 100644 --- a/lib/selective_disclosure/widget/display_selective_disclosure.dart +++ b/lib/selective_disclosure/widget/display_selective_disclosure.dart @@ -296,6 +296,7 @@ class DisclosureLine extends StatelessWidget { titleColor: Theme.of(context).colorScheme.onSurface, valueColor: Theme.of(context).colorScheme.onSurface, showVertically: showVertically, + type: elementValue['type'].toString(), ), ), if (elementValue['hasCheckbox'] == true) ...[ diff --git a/pubspec.lock b/pubspec.lock index 2fb5cb30f..ff6092b37 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -835,10 +835,10 @@ packages: dependency: transitive description: name: file_selector_macos - sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + sha256: cb284e267f8e2a45a904b5c094d2ba51d0aabfc20b1538ab786d9ef7dc2bf75c url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.9.4+1" file_selector_platform_interface: dependency: transitive description: @@ -2481,10 +2481,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" url_launcher_platform_interface: dependency: transitive description: @@ -2697,10 +2697,10 @@ packages: dependency: "direct main" description: name: x509 - sha256: "3262dc9a7d45b0876f886c01bfc7d5e765704f7dfd31f8cf5224fc875c17a6c6" + sha256: cbd1a63846884afd273cda247b0365284c8d85a365ca98e110413f93d105b935 url: "https://pub.dev" source: hosted - version: "0.2.4+2" + version: "0.2.4+3" x509_plus: dependency: transitive description: From c2e126b646a06d8390ca1bff1d39d38d6b90c533 Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Thu, 26 Sep 2024 12:13:40 +0000 Subject: [PATCH 5/7] version: 2.13.2+515 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f61e163f4..a6859b4fc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.13.1+514 +version: 2.13.2+515 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: From 5088fea57e7cbd8fac05f50fb071142ac77a16e6 Mon Sep 17 00:00:00 2001 From: hawkbee <49282360+hawkbee1@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:59:36 +0200 Subject: [PATCH 6/7] Disclosable child of undisclosable (#2912) * get a display * deal properly with json value inside selective disclosure which has a claim * Issuer metadata / display / type as "uri" to display as a link in the wallet #2907 * use value_type for profiles default, DIIP 2.1 and DIPP 3 --- .../credentials/detail/widgets/credential_subject_data.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dashboard/home/tab_bar/credentials/detail/widgets/credential_subject_data.dart b/lib/dashboard/home/tab_bar/credentials/detail/widgets/credential_subject_data.dart index 4a0de54f2..bf7b02d60 100644 --- a/lib/dashboard/home/tab_bar/credentials/detail/widgets/credential_subject_data.dart +++ b/lib/dashboard/home/tab_bar/credentials/detail/widgets/credential_subject_data.dart @@ -124,6 +124,7 @@ class CredentialSubjectData extends StatelessWidget { titleColor: Theme.of(context).colorScheme.onSurface, valueColor: Theme.of(context).colorScheme.onSurface, showVertically: showVertically, + type: value['value_type'].toString(), ); }).toList(), ); From 3e6799f7ff122d6892316f8cfa47b558d2405d92 Mon Sep 17 00:00:00 2001 From: hawkbee1 Date: Fri, 27 Sep 2024 09:08:46 +0000 Subject: [PATCH 7/7] version: 2.13.3+516 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a6859b4fc..5332bf802 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.13.2+515 +version: 2.13.3+516 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: