Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
Web wallet should be fully multi-wallet now
Browse files Browse the repository at this point in the history
  • Loading branch information
waltkb committed Nov 22, 2023
1 parent ab0b65e commit 07587e7
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 62 deletions.
7 changes: 7 additions & 0 deletions src/main/kotlin/id/walt/db/Db.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package id.walt.db
import id.walt.config.ConfigManager
import id.walt.config.DatasourceConfiguration
import id.walt.db.models.*
import id.walt.service.account.AccountsService
import id.walt.web.model.EmailAccountRequest
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.runBlocking
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.StdOutSqlLogger
Expand Down Expand Up @@ -67,6 +70,10 @@ object Db {
WalletDids,
WalletOperationHistories
)

runBlocking {
AccountsService.register(EmailAccountRequest("Max Mustermann", "[email protected]", "string"))
}
}

}
Expand Down
45 changes: 21 additions & 24 deletions src/main/kotlin/id/walt/service/SSIKit2WalletService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import java.net.URLDecoder
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.time.Duration.Companion.seconds


Expand Down Expand Up @@ -92,7 +91,7 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
it.document
}

override suspend fun deleteCredential(id: String) = CredentialsService.delete(walletId, id)
override suspend fun deleteCredential(id: String) = transaction { CredentialsService.delete(walletId, id) }

override suspend fun getCredential(credentialId: String): String =
CredentialsService.get(walletId, credentialId)?.document
Expand Down Expand Up @@ -225,7 +224,6 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
private val testCIClientConfig = OpenIDClientConfig("test-client", null, redirectUri = "http://blank")


@OptIn(ExperimentalEncodingApi::class)
override suspend fun useOfferRequest(offer: String, did: String) {
val credentialWallet = getCredentialWallet(did)

Expand Down Expand Up @@ -327,9 +325,8 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
throw IllegalStateException("No credential was returned from credentialEndpoint: $credentialResponses")
}

credentialResponses.forEachIndexed { index, credentialResp ->
val addableCredentials: List<WalletCredential> = credentialResponses.map { credentialResp ->
val credential = credentialResp.credential!!.jsonPrimitive.content
println(">>> $index. CREDENTIAL IS: $credential")

val credentialJwt = credential.decodeJws()

Expand All @@ -338,17 +335,13 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
val credentialId = credentialJwt.payload["vc"]!!.jsonObject["id"]?.jsonPrimitive?.content?.takeIf { it.isNotBlank() }
?: randomUUID()

CredentialsService.add(
WalletCredential(
wallet = walletId,
WalletCredential(
wallet = walletId,
id = credentialId,
document = credential,
disclosures = null,
addedOn = Clock.System.now()
)
id = credentialId,
document = credential,
disclosures = null,
addedOn = Clock.System.now()
)
println(">>> $index. CREDENTIAL stored with Id: $credentialId")
}

"vc+sd-jwt" -> {
Expand All @@ -358,23 +351,26 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
val disclosures = credentialJwt.signature.split("~").drop(1)
val disclosuresString = disclosures.joinToString("~")

CredentialsService.add(
WalletCredential(
wallet = walletId,
WalletCredential(
wallet = walletId,
id = credentialId,
document = credential,
disclosures = disclosuresString,
addedOn = Clock.System.now()
)
id = credentialId,
document = credential,
disclosures = disclosuresString,
addedOn = Clock.System.now()
)
println(">>> $index. CREDENTIAL stored with Id: $credentialId")
}

null -> throw IllegalArgumentException("WalletCredential JWT does not have \"typ\"")
else -> throw IllegalArgumentException("Invalid credential \"typ\": $typ")
}
}

transaction {
CredentialsService.addAll(
wallet = walletId,
credentials = addableCredentials
)
}
}

/* DIDs */
Expand Down Expand Up @@ -404,7 +400,7 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
return result.did
}

override suspend fun listDids() = DidsService.list(walletId)
override suspend fun listDids() = transaction { DidsService.list(walletId) }

override suspend fun loadDid(did: String): JsonObject = DidsService.get(walletId, did)?.let {
Json.parseToJsonElement(it.document).jsonObject
Expand Down Expand Up @@ -518,6 +514,7 @@ class SSIKit2WalletService(accountId: UUID, walletId: UUID) : WalletService(acco
transaction {
WalletOperationHistories.insert {
it[account] = operationHistory.account.toJavaUUID()
it[wallet] = operationHistory.wallet.toJavaUUID()
it[timestamp] = operationHistory.timestamp.toJavaInstant()
it[operation] = operationHistory.operation
it[data] = Json.encodeToString(operationHistory.data)
Expand Down
29 changes: 17 additions & 12 deletions src/main/kotlin/id/walt/service/credentials/CredentialsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,31 @@ import kotlinx.uuid.UUID
import kotlinx.uuid.toJavaUUID
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.batchInsert
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction

object CredentialsService {
fun get(wallet: UUID, credentialId: String): WalletCredential? =
fun get(wallet: UUID, credentialId: String): WalletCredential? = transaction {
WalletCredentials.select { (WalletCredentials.wallet eq wallet.toJavaUUID()) and (WalletCredentials.id eq credentialId) }
.singleOrNull()?.let { WalletCredential(it) }
}

fun list(wallet: UUID) = WalletCredentials.select { WalletCredentials.wallet eq wallet.toJavaUUID() }
.map { WalletCredential(it) }
fun list(wallet: UUID) = transaction {
WalletCredentials.select { WalletCredentials.wallet eq wallet.toJavaUUID() }
.map { WalletCredential(it) }
}

fun add(wallet: UUID, credential: WalletCredential): String =
WalletCredentials.insert {
it[WalletCredentials.wallet] = wallet.toJavaUUID()
it[id] = credential.id
it[document] = credential.document
it[disclosures] = credential.disclosures
it[addedOn] = Clock.System.now().toJavaInstant()
}[WalletCredentials.id]
fun add(wallet: UUID, vararg credentials: WalletCredential) = addAll(wallet, credentials.toList())
fun addAll(wallet: UUID, credentials: List<WalletCredential>): List<String> =
WalletCredentials.batchInsert(credentials) { credential: WalletCredential ->
this[WalletCredentials.wallet] = wallet.toJavaUUID()
this[WalletCredentials.id] = credential.id
this[WalletCredentials.document] = credential.document
this[WalletCredentials.disclosures] = credential.disclosures
this[WalletCredentials.addedOn] = Clock.System.now().toJavaInstant()
}.map { it[WalletCredentials.id] }

fun delete(wallet: UUID, credentialId: String): Boolean =
WalletCredentials.deleteWhere { (WalletCredentials.wallet eq wallet.toJavaUUID()) and (id eq credentialId) } > 0
Expand Down
18 changes: 11 additions & 7 deletions src/main/kotlin/id/walt/service/dids/DidService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import kotlinx.uuid.UUID
import kotlinx.uuid.toJavaUUID
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction

object DidsService {
fun get(wallet: UUID, did: String): WalletDid? =
fun get(wallet: UUID, did: String): WalletDid? = transaction {
WalletDids.select { (WalletDids.wallet eq wallet.toJavaUUID()) and (WalletDids.did eq did) }
.singleOrNull()?.let { WalletDid(it) }
}

fun list(wallet: UUID): List<WalletDid> = WalletDids.select { WalletDids.wallet eq wallet.toJavaUUID() }.map { WalletDid(it) }

Expand All @@ -34,12 +36,14 @@ object DidsService {


fun makeDidDefault(wallet: UUID, newDefaultDid: String) {
WalletDids.update({ (WalletDids.wallet eq wallet.toJavaUUID()) and (WalletDids.default eq true) }) {
it[default] = false
}

WalletDids.update({ (WalletDids.wallet eq wallet.toJavaUUID()) and (WalletDids.did eq newDefaultDid) }) {
it[default] = true
transaction {
WalletDids.update({ (WalletDids.wallet eq wallet.toJavaUUID()) and (WalletDids.default eq true) }) {
it[default] = false
}

WalletDids.update({ (WalletDids.wallet eq wallet.toJavaUUID()) and (WalletDids.did eq newDefaultDid) }) {
it[default] = true
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions web/src/components/WalletPageHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<template v-slot:menu>
<NuxtLink
class="inline-flex focus:outline focus:outline-blue-600 focus:outline-offset-2 items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
:to="`/wallet/${currentWallet.value}/settings/issuers`"
:to="`/wallet/${currentWallet}/settings/issuers`"
type="button"
v-if="currentWallet"
>
Expand All @@ -33,7 +33,7 @@
</NuxtLink>
<NuxtLink
class="inline-flex focus:outline focus:outline-blue-600 focus:outline-offset-2 items-center rounded-md bg-blue-500 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
to="scan"
:to="`/wallet/${currentWallet}/scan`"
type="button"
>
<QrCodeIcon class="h-5 w-5 mr-1" />
Expand Down
4 changes: 3 additions & 1 deletion web/src/pages/api/siop/initiateIssuance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
import CenterMain from "~/components/CenterMain.vue";
import LoadingIndicator from "~/components/loading/LoadingIndicator.vue";
const currentWallet = useCurrentWallet()
if (process.client) {
const url = "openid-initiate-issuance://" + new URL(window.location.href).search;
console.log(url);
const encoded = btoa(url);
console.log(encoded);
navigateTo(`/exchange/issuance?request=${encoded}`);
navigateTo(`/wallet/${currentWallet.value}/exchange/issuance?request=${encoded}`);
}
</script>

Expand Down
4 changes: 3 additions & 1 deletion web/src/pages/api/siop/initiatePresentation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import CenterMain from "~/components/CenterMain.vue";
import LoadingIndicator from "~/components/loading/LoadingIndicator.vue";
import { encodeRequest, fixRequest } from "~/composables/siop-requests";
const currentWallet = useCurrentWallet()
if (process.client) {
let request = encodeURI(decodeURI(fixRequest("openid://" + window.location.search)));
console.log("Fixed request: ", request);
const encoded = encodeRequest(request);
console.log("Encoded request: ", encoded);
navigateTo({ path: "/exchange/presentation", query: { request: encoded } });
navigateTo({ path: `/wallet/${currentWallet.value}/exchange/presentation`, query: { request: encoded } });
}
</script>

Expand Down
12 changes: 8 additions & 4 deletions web/src/pages/help/[...slug].vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<script lang="ts" setup>
import CenterMain from "~/components/CenterMain.vue";
</script>

<template>
<CenterMain>
<ContentDoc />
</CenterMain>
</template>

<script lang="ts" setup>
import CenterMain from "~/components/CenterMain.vue";
definePageMeta({
layout: "default-reduced-nav",
})
</script>

<style scoped>
h1 {
font-size: 40px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
display-text="Reject"
icon="heroicons:x-mark"
type="button"
@click="navigateTo('/')"
@click="navigateTo(`/wallet/${currentWallet.value}`)"
/>

<div class="group flex">
Expand Down Expand Up @@ -150,10 +150,10 @@ import LoadingIndicator from "~/components/loading/LoadingIndicator.vue";
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from "@headlessui/vue";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
import { useTitle } from "@vueuse/core";
import { Ref } from "vue";
import { ref } from "vue";
const currentWallet = useCurrentWallet()
const { data: dids, pending: pendingDids } = await useLazyAsyncData(() => $fetch(`/r/wallet/${currentWallet}/dids`));
const { data: dids, pending: pendingDids } = await useLazyAsyncData(() => $fetch(`/r/wallet/${currentWallet.value}/dids`));
const selectedDid: Ref<Object | null> = ref(null);
Expand Down Expand Up @@ -212,6 +212,7 @@ const credentialList = issuanceParamsJson["credentials"];
let credentialTypes: String[] = [];
for (let credentialListElement of credentialList) {
console.log(`Processing: ${credentialListElement}`)
const typeList = credentialListElement["types"] as Array<String>;
const lastType = typeList[typeList.length - 1] as String;
Expand Down Expand Up @@ -246,7 +247,7 @@ async function acceptCredential() {
method: "POST",
body: request,
});
navigateTo("/");
navigateTo(`/wallet/${currentWallet.value}`);
} catch (e) {
failed.value = true;
failMessage.value = JSON.stringify(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
display-text="Reject"
icon="heroicons:x-mark"
type="button"
@click="navigateTo('/')"
@click="navigateTo(`/wallet/${currentWallet.value}`)"
/>

<div class="group flex">
Expand Down Expand Up @@ -138,7 +138,8 @@ async function acceptPresentation() {
external: true,
});
} else {
navigateTo("", {
window.alert("Presentation successful, no redirect URL supplied.")
navigateTo(`/wallet/${currentWallet.value}`, {
external: true,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import CenterMain from "~/components/CenterMain.vue";
import ManualRequestEntry from "~/components/scan/ManualRequestEntry.vue";
import { encodeRequest, fixRequest } from "~/composables/siop-requests";
const currentWallet = useCurrentWallet()
async function startRequest(request) {
console.log("Start request:", request);
request = fixRequest(request);
Expand All @@ -34,12 +36,12 @@ async function startRequest(request) {
console.log("Using encoded request:", encoded);
if (type === SiopRequestType.ISSUANCE) {
await navigateTo({ path: "/exchange/issuance", query: { request: encoded } });
await navigateTo({ path: `/wallet/${currentWallet.value}/exchange/issuance`, query: { request: encoded } });
} else if (type === SiopRequestType.PRESENTATION) {
await navigateTo({ path: "/exchange/presentation", query: { request: encoded } });
await navigateTo({ path: `/wallet/${currentWallet.value}/exchange/presentation`, query: { request: encoded } });
} else {
console.error("Unknown SIOP request type");
await navigateTo({ path: "/exchange/error", query: { message: btoa("Unknown request type") } });
await navigateTo({ path: `/wallet/${currentWallet.value}/exchange/error`, query: { message: btoa("Unknown request type") } });
}
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion web/src/pages/wallet/[wallet]/settings/dids/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

<div class="flex flex-none items-center gap-x-4">
<NuxtLink
:to="'/settings/dids/' + did.did"
:to="`/wallet/${currentWallet}/settings/dids/${did.did}`"
class="hidden rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:block"
>
View DID
Expand Down
2 changes: 1 addition & 1 deletion web/src/pages/wallet/[wallet]/settings/issuers/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</div>
<div class="flex flex-none items-center gap-x-4">
<NuxtLink
:to="'/settings/issuers/' + issuer.name"
:to="`/wallet/${currentWallet.value}/settings/issuers/${issuer.name}`"
class="hidden rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:block"
>
View supported credentials
Expand Down

0 comments on commit 07587e7

Please sign in to comment.