@@ -33,7 +33,6 @@ import org.multipaz.provisioning.evidence.EvidenceRequestMessage
33
33
import org.multipaz.provisioning.evidence.EvidenceRequestOpenid4Vp
34
34
import org.multipaz.provisioning.evidence.EvidenceRequestQuestionMultipleChoice
35
35
import org.multipaz.provisioning.evidence.EvidenceRequestQuestionString
36
- import org.multipaz.provisioning.evidence.EvidenceRequestSetupCloudSecureArea
37
36
import org.multipaz.provisioning.evidence.EvidenceRequestWeb
38
37
import org.multipaz.provisioning.evidence.EvidenceResponseCreatePassphrase
39
38
import org.multipaz.provisioning.evidence.EvidenceResponseMessage
@@ -44,28 +43,48 @@ import com.android.identity.testapp.provisioning.model.ProvisioningModel
44
43
import kotlinx.coroutines.delay
45
44
import kotlinx.coroutines.launch
46
45
import kotlinx.coroutines.withContext
46
+ import kotlinx.serialization.json.Json
47
+ import kotlinx.serialization.json.buildJsonObject
48
+ import kotlinx.serialization.json.jsonObject
49
+ import kotlinx.serialization.json.jsonPrimitive
50
+ import kotlinx.serialization.json.put
51
+ import org.jetbrains.compose.resources.painterResource
47
52
import org.multipaz.compose.PassphraseEntryField
53
+ import org.multipaz.compose.presentment.Presentment
48
54
import org.multipaz.compose.webview.RichText
49
55
import org.multipaz.credential.Credential
50
- import org.multipaz.prompt.PromptModel
56
+ import org.multipaz.models.presentment.DigitalCredentialsPresentmentMechanism
57
+ import org.multipaz.models.presentment.PresentmentModel
51
58
import org.multipaz.provisioning.ApplicationSupport
52
59
import org.multipaz.provisioning.LandingUrlUnknownException
53
60
import org.multipaz.provisioning.evidence.EvidenceRequestNotificationPermission
54
61
import org.multipaz.provisioning.evidence.EvidenceResponseNotificationPermission
55
- import org.multipaz.securearea.SecureAreaRepository
56
- import org.multipaz.securearea.cloud.CloudSecureArea
62
+ import org.multipaz.provisioning.evidence.EvidenceResponseOpenid4Vp
63
+ import org.multipaz.testapp.App
64
+ import org.multipaz.testapp.TestAppPresentmentSource
65
+ import org.multipaz.testapp.platformAppIcon
66
+ import org.multipaz.testapp.platformAppName
57
67
import org.multipaz.util.Logger
58
68
import kotlin.time.Duration.Companion.seconds
59
69
60
70
@Composable
61
- fun ProvisioningTestScreen (promptModel : PromptModel , provisioningModel : ProvisioningModel ) {
71
+ fun ProvisioningTestScreen (
72
+ app : App ,
73
+ provisioningModel : ProvisioningModel ,
74
+ presentmentModel : PresentmentModel
75
+ ) {
62
76
LaunchedEffect (provisioningModel) {
63
77
provisioningModel.run ()
64
78
}
65
79
val provisioningState = provisioningModel.state.collectAsState(ProvisioningModel .Initial ).value
66
80
Column {
67
81
if (provisioningState is ProvisioningModel .EvidenceRequested ) {
68
- RequestEvidence (provisioningModel, promptModel, provisioningState)
82
+ RequestEvidence (
83
+ app,
84
+ provisioningModel,
85
+ presentmentModel,
86
+ provisioningState
87
+ )
69
88
} else {
70
89
val text = when (provisioningState) {
71
90
ProvisioningModel .Initial -> " Starting provisioning..."
@@ -91,13 +110,14 @@ fun ProvisioningTestScreen(promptModel: PromptModel, provisioningModel: Provisio
91
110
92
111
@Composable
93
112
private fun RequestEvidence (
113
+ app : App ,
94
114
provisioningModel : ProvisioningModel ,
95
- promptModel : PromptModel ,
115
+ presentmentModel : PresentmentModel ,
96
116
request : ProvisioningModel .EvidenceRequested
97
117
) {
98
118
val index = remember { mutableIntStateOf(0 ) }
99
119
val evidenceRequest = request.evidenceRequests[index.value]
100
- val coroutineScope = rememberCoroutineScope { promptModel }
120
+ val coroutineScope = rememberCoroutineScope { app. promptModel }
101
121
when (evidenceRequest) {
102
122
is EvidenceRequestQuestionString -> {
103
123
EvidenceRequestQuestionStringView (
@@ -154,7 +174,10 @@ private fun RequestEvidence(
154
174
155
175
is EvidenceRequestOpenid4Vp -> {
156
176
EvidenceRequestOpenid4VpView (
177
+ app = app,
178
+ provisioningModel = provisioningModel,
157
179
evidenceRequest = evidenceRequest,
180
+ presentmentModel = presentmentModel,
158
181
viableCredentials = request.credentials,
159
182
onNextEvidenceRequest = {
160
183
index.value++
@@ -542,31 +565,81 @@ private suspend fun handleLanding(
542
565
543
566
@Composable
544
567
fun EvidenceRequestOpenid4VpView (
568
+ app : App ,
569
+ provisioningModel : ProvisioningModel ,
545
570
evidenceRequest : EvidenceRequestOpenid4Vp ,
571
+ presentmentModel : PresentmentModel ,
546
572
viableCredentials : List <Credential >,
547
573
onNextEvidenceRequest : () -> Unit
548
574
) {
549
- Column {
550
- Row (
551
- modifier = Modifier .fillMaxWidth(),
552
- horizontalArrangement = Arrangement .Center
553
- ) {
554
- Text (
555
- text = " Presentation during issuance is not yet implemented" ,
556
- textAlign = TextAlign .Center ,
557
- modifier = Modifier .padding(8 .dp),
558
- style = MaterialTheme .typography.titleLarge
559
- )
560
- }
561
- Row (
562
- modifier = Modifier .fillMaxWidth(),
563
- horizontalArrangement = Arrangement .Center
564
- ) {
565
- Button (
566
- modifier = Modifier .padding(8 .dp),
567
- onClick = onNextEvidenceRequest
575
+ val coroutineScope = rememberCoroutineScope()
576
+ val presenting = remember { mutableStateOf(false ) }
577
+ if (presenting.value) {
578
+ Presentment (
579
+ presentmentModel = presentmentModel,
580
+ promptModel = app.promptModel,
581
+ documentTypeRepository = app.documentTypeRepository,
582
+ source = TestAppPresentmentSource (app),
583
+ onPresentmentComplete = { presenting.value = false },
584
+ appName = platformAppName,
585
+ appIconPainter = painterResource(platformAppIcon),
586
+ )
587
+ } else {
588
+ Column {
589
+ Row (
590
+ modifier = Modifier .fillMaxWidth(),
591
+ horizontalArrangement = Arrangement .Center
592
+ ) {
593
+ Text (
594
+ text = " Presentation during issuance" ,
595
+ textAlign = TextAlign .Center ,
596
+ modifier = Modifier .padding(8 .dp),
597
+ style = MaterialTheme .typography.titleLarge
598
+ )
599
+ }
600
+ Row (
601
+ modifier = Modifier .fillMaxWidth(),
602
+ horizontalArrangement = Arrangement .Center
568
603
) {
569
- Text (text = evidenceRequest.cancelText ? : " Use browser" )
604
+ Button (
605
+ modifier = Modifier .padding(8 .dp),
606
+ onClick = {
607
+ presentmentModel.reset()
608
+ val mechanism = object : DigitalCredentialsPresentmentMechanism (
609
+ appId = " " ,
610
+ webOrigin = evidenceRequest.originUri,
611
+ protocol = " openid4vp" ,
612
+ request = buildJsonObject {
613
+ put(" request" , evidenceRequest.request)
614
+ }.toString(),
615
+ document = viableCredentials.first().document
616
+ ) {
617
+ override fun sendResponse (response : String ) {
618
+ coroutineScope.launch {
619
+ val json = Json .parseToJsonElement(response).jsonObject
620
+ provisioningModel.provideEvidence(
621
+ EvidenceResponseOpenid4Vp (json[" response" ]!! .jsonPrimitive.content)
622
+ )
623
+ }
624
+ }
625
+
626
+ override fun close () {
627
+ presenting.value = false
628
+ }
629
+ }
630
+ presentmentModel.setConnecting()
631
+ presentmentModel.setMechanism(mechanism)
632
+ presenting.value = true
633
+ }
634
+ ) {
635
+ Text (text = " Present Credential" )
636
+ }
637
+ Button (
638
+ modifier = Modifier .padding(8 .dp),
639
+ onClick = onNextEvidenceRequest
640
+ ) {
641
+ Text (text = evidenceRequest.cancelText ? : " Use browser" )
642
+ }
570
643
}
571
644
}
572
645
}
0 commit comments