Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature multi presentation #29

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions tw2023_wallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
8B80569C2B5F7815009A87C8 /* SharingCredentialArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B80569B2B5F7815009A87C8 /* SharingCredentialArgs.swift */; };
8B80569D2B5F7815009A87C8 /* SharingCredentialArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B80569B2B5F7815009A87C8 /* SharingCredentialArgs.swift */; };
8B80569F2B60E2FB009A87C8 /* PreferencesDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B80569E2B60E2FB009A87C8 /* PreferencesDataStore.swift */; };
8B8056A12B6381BD009A87C8 /* CredentialSharingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B8056A02B6381BD009A87C8 /* CredentialSharingModel.swift */; };
8B81E29D2B33CC4000ED3B4E /* tw2023_walletApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B81E29C2B33CC4000ED3B4E /* tw2023_walletApp.swift */; };
8B81E29F2B33CC4000ED3B4E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B81E29E2B33CC4000ED3B4E /* ContentView.swift */; };
8B81E2A12B33CC4200ED3B4E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B81E2A02B33CC4200ED3B4E /* Assets.xcassets */; };
Expand Down Expand Up @@ -340,7 +339,6 @@
8B774A532B7B7B5400F5ED55 /* QRReaderViewLauncher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRReaderViewLauncher.swift; sourceTree = "<group>"; };
8B80569B2B5F7815009A87C8 /* SharingCredentialArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingCredentialArgs.swift; sourceTree = "<group>"; };
8B80569E2B60E2FB009A87C8 /* PreferencesDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesDataStore.swift; sourceTree = "<group>"; };
8B8056A02B6381BD009A87C8 /* CredentialSharingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialSharingModel.swift; sourceTree = "<group>"; };
8B81E2992B33CC4000ED3B4E /* tw2023_wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tw2023_wallet.app; sourceTree = BUILT_PRODUCTS_DIR; };
8B81E29C2B33CC4000ED3B4E /* tw2023_walletApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = tw2023_walletApp.swift; sourceTree = "<group>"; };
8B81E29E2B33CC4000ED3B4E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -886,7 +884,6 @@
children = (
8B81E2F92B35AC0C00ED3B4E /* CredentialListModel.swift */,
F657D5CE2B3C469500901A6A /* CredentialDetailModel.swift */,
8B8056A02B6381BD009A87C8 /* CredentialSharingModel.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -1652,7 +1649,6 @@
F6CC769C2B57CDB900FA26A8 /* QRCodeGenerator.swift in Sources */,
F6CC768D2B567A7B00FA26A8 /* QrCodeCameraDelegate.swift in Sources */,
F6BB10352B4FA1D60063DBBF /* RecipientOrgInfo.swift in Sources */,
8B8056A12B6381BD009A87C8 /* CredentialSharingModel.swift in Sources */,
F699A8D52B3FF6B500F60B91 /* CredentialOfferPreviewModel.swift in Sources */,
F621E1F52B6C6A610034BF95 /* RecipientDetailArgs.swift in Sources */,
A83039C92B4E6E7E004139A7 /* credential_data.proto in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/skywinder/web3swift",
"state" : {
"revision" : "74c24f4d3d5f1816616e9ebd16741ca5f7a57eb0",
"version" : "3.2.0"
"revision" : "8a026108ae5ff730ac83e9b574c8cf1c14413c94",
"version" : "3.2.2"
}
},
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class CredentialListViewModel {
let ret = matchVcToRequirement(
sdJwt: credential.payload, presentationDefinition: presentationDefinition)
if let (_, disclosures) = ret {
return 0 < disclosures.filter { it in (it.isUserSelectable || it.isSubmit) }.count
return 0
< disclosures.filter { it in (it.isUserSelectable || it.isSubmit) }.count
}
return false
}
Expand Down
14 changes: 6 additions & 8 deletions tw2023_wallet/Feature/Credentials/Views/CredentialDetail.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import SwiftUI
struct CredentialDetail: View {
@Environment(\.presentationMode) var presentationMode
@Environment(SharingRequestModel.self) var sharingRequestModel: SharingRequestModel?
// @Environment(CredentialSharingModel.self) var credentialSharingModel: CredentialSharingModel?
var credential: Credential
var viewModel: CredentialDetailViewModel
var deleteAction: (() -> Void)?
Expand Down Expand Up @@ -145,17 +144,16 @@ struct CredentialDetail: View {
ActionButtonBlack(
title: "Select This Credential",
action: {
let claims = (viewModel.requiredClaims + userSelectableClaims).filter
{ it in
it.isSubmit
}
let claims = (viewModel.requiredClaims + userSelectableClaims)
.filter { it in
it.isSubmit
}
let submissionCredential = viewModel.createSubmissionCredential(
credential: credential,
discloseClaims: claims
)
sharingRequestModel?.setSelectedCredential(
data: submissionCredential,
submissionClaims: claims,
sharingRequestModel?.setSelectedCredentials(
data: [submissionCredential],
metadata: credential.metaData
)
path.removeLast(2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ class SharingRequestModel {
}

var type: String? = nil
var data: SubmissionCredential? = nil
var data: [SubmissionCredential]? = nil
var metadata: CredentialIssuerMetadata? = nil
var submissionClaims: [DisclosureWithOptionality]? = nil
func setSelectedCredential(
data: SubmissionCredential, submissionClaims: [DisclosureWithOptionality],
func setSelectedCredentials(
data: [SubmissionCredential],
metadata: CredentialIssuerMetadata
) {
self.data = data
self.submissionClaims = submissionClaims
self.metadata = metadata
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ struct SharingRequest: View {
viewModel.selectedCredential
{
let result = await viewModel.shareVpToken(
credentials: [sharingRequestModel.data!]
credentials: sharingRequestModel.data!
)
switch result {
case .success(let postResult):
Expand Down Expand Up @@ -213,11 +213,12 @@ struct SharingRequest: View {
if sharingRequestModel.data != nil {
viewModel.selectedCredential = true
if let submission = sharingRequestModel.data,
let metadata = sharingRequestModel.metadata
let metadata = sharingRequestModel.metadata,
let firstSubmission = submission.first // Workaround until multiple credentials are possible on the UI.
{
if let credentialSupported = VCIMetadataUtil.findMatchingCredentials(
format: submission.format,
types: submission.types,
format: firstSubmission.format,
types: firstSubmission.types,
metadata: metadata
) {
if let display = credentialSupported.display {
Expand Down
72 changes: 36 additions & 36 deletions tw2023_wallet/Services/OID/OpenIdProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,12 @@ class OpenIdProvider {
}

let vpTokens = try! credentials.compactMap {
credential -> (String, (String, DescriptorMap, [DisclosedClaim], String?))? in
credential -> (String, PreparedSubmissionData)? in
switch credential.format {
case "vc+sd-jwt":
return (
credential.id,
try createPresentationSubmissionSdJwtVc(
try createVpTokenForSdJwtVc(
credential: credential,
presentationDefinition: presentationDefinition,
clientId: clientId,
Expand All @@ -448,7 +448,7 @@ class OpenIdProvider {
case "jwt_vc_json":
return (
credential.id,
try createPresentationSubmissionJwtVc(
try createVpTokenForJwtVc(
credential: credential,
presentationDefinition: presentationDefinition,
clientId: clientId,
Expand All @@ -463,10 +463,10 @@ class OpenIdProvider {

let vpTokenValue: String
if vpTokens.count == 1 {
vpTokenValue = vpTokens[0].1.0
vpTokenValue = vpTokens[0].1.vpToken
}
else if !vpTokens.isEmpty {
let tokens = vpTokens.map { $0.1.0 }
let tokens = vpTokens.map { $0.1.vpToken }
let jsonEncoder = JSONEncoder()
if let jsonData = try? jsonEncoder.encode(tokens),
let jsonString = String(data: jsonData, encoding: .utf8)
Expand All @@ -484,7 +484,7 @@ class OpenIdProvider {
let presentationSubmission = PresentationSubmission(
id: UUID().uuidString,
definitionId: presentationDefinition.id,
descriptorMap: vpTokens.map { $0.1.1 }
descriptorMap: vpTokens.map { $0.1.descriptorMap }
)

let jsonEncoder = JSONEncoder()
Expand All @@ -507,20 +507,22 @@ class OpenIdProvider {
convert: convertVpTokenResponseResponse,
using: session
)
let sharedContents = vpTokens.map { SharedContent(id: $0.0, sharedClaims: $0.1.2) }
let purposes = vpTokens.map { $0.1.3 }
let sharedContents = vpTokens.map {
SharedContent(id: $0.0, sharedClaims: $0.1.disclosedClaims)
}
let purposes = vpTokens.map { $0.1.purpose }
return .success((postResult, sharedContents, purposes))
}
catch {
return .failure(error)
}
}
func createPresentationSubmissionSdJwtVc(
func createVpTokenForSdJwtVc(
credential: SubmissionCredential,
presentationDefinition: PresentationDefinition,
clientId: String,
nonce: String
) throws -> (String, DescriptorMap, [DisclosedClaim], String?) {
) throws -> PreparedSubmissionData {
// ここに実装を追加します
let sdJwt = credential.credential

Expand All @@ -529,14 +531,7 @@ class OpenIdProvider {
let (inputDescriptor, _) = matchVcToRequirement(
sdJwt: sdJwt, presentationDefinition: presentationDefinition)
else {
// TODO: エラーハンドリングかダミーの戻り値
return (
"Dummy",
DescriptorMap(
id: "dummyId", format: "dummyFormat", path: "dummyPath",
pathNested: Path(format: "dummyFormat", path: "dummyPath")), [DisclosedClaim](),
"dummyPurpose"
)
throw OpenIdProviderIllegalInputException.illegalCredentialInput
}
let selectedDisclosures = credential.discloseClaims.map { $0.disclosure }
print(String(describing: inputDescriptor))
Expand All @@ -548,13 +543,7 @@ class OpenIdProvider {

let parts = sdJwt.split(separator: "~").map(String.init)
guard let issuerSignedJwt = parts.first else {
return (
"Error",
DescriptorMap(
id: "error", format: "error", path: "error",
pathNested: Path(format: "error", path: "error")), [DisclosedClaim](),
"dummyPurpose"
)
throw OpenIdProviderIllegalInputException.illegalCredentialInput
}

let hasNilValue = selectedDisclosures.contains { disclosure in
Expand Down Expand Up @@ -585,14 +574,16 @@ class OpenIdProvider {
id: credential.id, types: credential.types, name: key, value: disclosure.value)
}

return (vpToken, dm, disclosedClaims, inputDescriptor.purpose)
return PreparedSubmissionData(
vpToken: vpToken, descriptorMap: dm, disclosedClaims: disclosedClaims,
purpose: inputDescriptor.purpose)
}

func createPresentationSubmissionJwtVc(
func createVpTokenForJwtVc(
credential: SubmissionCredential,
presentationDefinition: PresentationDefinition,
clientId: String, nonce: String
) throws -> (String, DescriptorMap, [DisclosedClaim], String?) {
) throws -> PreparedSubmissionData {
do {
let (_, payload, _) = try JWTUtil.decodeJwt(jwt: credential.credential)
if let vcDictionary = payload["vc"] as? [String: Any],
Expand All @@ -613,11 +604,11 @@ class OpenIdProvider {

let descriptorMap = JwtVpJsonPresentation.genDescriptorMap(
inputDescriptorId: credential.inputDescriptor.id)
return (
vpToken,
descriptorMap,
disclosedClaims,
nil
return PreparedSubmissionData(
vpToken: vpToken,
descriptorMap: descriptorMap,
disclosedClaims: disclosedClaims,
purpose: nil
)
}
else {
Expand Down Expand Up @@ -727,6 +718,13 @@ struct SubmissionCredential: Codable, Equatable {
}
}

struct PreparedSubmissionData {
let vpToken: String
let descriptorMap: DescriptorMap
let disclosedClaims: [DisclosedClaim]
let purpose: String?
}

struct DisclosedClaim: Codable {
let id: String // credential identifier
let types: [String]
Expand Down Expand Up @@ -811,7 +809,8 @@ func matchVcToRequirement(sdJwt: String, presentationDefinition: PresentationDef
// 各InputDescriptorをループ
for inputDescriptor in presentationDefinition.inputDescriptors {
// fieldKeysを取得
let requiredOrOptionalKeys = filterKeysWithOptionality(from: sourcePayload, using: inputDescriptor)
let requiredOrOptionalKeys = filterKeysWithOptionality(
from: sourcePayload, using: inputDescriptor)

let matchingDisclosures = createDisclosureWithOptionality(
from: allDisclosures,
Expand All @@ -831,7 +830,7 @@ private func filterKeysWithOptionality(
/*
array of (String, Bool) values filtered by `inputDescriptor.constraints.fields.path`
A Bool value represents whether the field is required.

example of input_descriptors
"input_descriptors": [
{
Expand Down Expand Up @@ -870,7 +869,8 @@ private func createDisclosureWithOptionality(
disclosure: disclosure, isSubmit: !optionality, isUserSelectable: optionality)
}
}
return DisclosureWithOptionality(disclosure: disclosure, isSubmit: false, isUserSelectable: false)
return DisclosureWithOptionality(
disclosure: disclosure, isSubmit: false, isUserSelectable: false)
}
}

Expand Down
2 changes: 1 addition & 1 deletion tw2023_wallet/Services/OID/PresentationExchange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ struct PresentationSubmission: Codable {

struct DisclosureWithOptionality: Codable {
var disclosure: Disclosure

// If the value of `isUserSelectable` is `true`, the value of `isSubmit`
// is a mutable that can be changed by the user (via toggle operation).
var isSubmit: Bool
Expand Down
Loading
Loading