Skip to content

Commit

Permalink
Discovery: allow registration parameters to be passed
Browse files Browse the repository at this point in the history
  • Loading branch information
reinkrul committed Oct 18, 2024
1 parent 447878f commit 6bcc884
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 20 deletions.
52 changes: 51 additions & 1 deletion deploy/discovery/dev_eOverdracht2023.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,20 @@
"JsonWebSignature2020"
]
},
"jwt_vc": {
"alg": [
"ES256"
]
},
"ldp_vp": {
"proof_type": [
"JsonWebSignature2020"
]
},
"jwt_vp": {
"alg": ["ES256"]
"alg": [
"ES256"
]
}
},
"input_descriptors": [
Expand Down Expand Up @@ -48,6 +60,44 @@
}
]
}
},
{
"id": "id_registration_parameters_credential",
"name": "Registration parameters",
"purpose": "Finding endpoints registered by the care organization.",
"constraints": {
"fields": [
{
"path": [
"$.type"
],
"filter": {
"type": "string",
"const": "DiscoveryRegistrationCredential"
}
},
{
"id": "authorization_server_url",
"purpose": "Used by clients to request OAuth2 access tokens.",
"path": [
"$.credentialSubject.authServerURL"
],
"filter": {
"type": "string"
}
},
{
"id": "fhir_notification_url",
"purpose": "FHIR subscription REST channel endpoint, issued by SCP-nodes notify about FHIR resources.",
"path": [
"$.credentialSubject.fhirNotificationURL"
],
"filter": {
"type": "string"
}
}
]
}
}
]
}
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ services:
NUTS_STRICTMODE: false
NUTS_DISCOVERY_DEFINITIONS_DIRECTORY: /opt/nuts/discovery
NUTS_POLICY_DIRECTORY: /opt/nuts/policy
NUTS_AUTH_CONTRACTVALIDATORS: dummy
# nuts-admin:
# build:
# context: .
Expand Down
123 changes: 123 additions & 0 deletions web/src/admin/ActivateDiscoveryService.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<template>
<div>
<h1>Activate Discovery Service</h1>
<p>
This page allows you to activate a discovery service for a subject.
</p>
<p v-if="fetchError" class="m-4">Error: {{ fetchError }}</p>
<section v-if="selectedDiscoveryService">
<header>Discovery Service</header>
<div>
<label for="subjectID">Subject ID</label>
<input id="subjectID" v-model="$route.params.subjectID" type="text" readonly>
</div>
<div>
<label for="discoveryServiceID">Discovery Service</label>
<input id="discoveryServiceID" v-model="selectedDiscoveryService.id" type="text" readonly>
</div>
<div>
<label for="discoveryServiceEndpoint">Endpoint</label>
<input id="discoveryServiceEndpoint" v-model="selectedDiscoveryService.endpoint" type="text" readonly>
</div>
</section>

<section>
<header>Parameters</header>
<a v-on:click="registrationParameters.push({})" style="cursor: pointer">Add a parameter</a>
<table class="w-full">
<thead>
<tr>
<th class="w-1/3">Key</th>
<th>Value</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(param, idx) in registrationParameters" :key="'search-' + idx">
<td style="vertical-align: top">
<input type="text" v-model="param.key" :id="'param-key-' + idx">
<div if="param.label" style="padding-left: 10px;">{{ param.label }}</div>
</td>
<td style="vertical-align: top">
<input type="text" v-model="param.value" v-on:keyup="search" :id="'param-value-' + idx">
</td>
<td style="vertical-align: top; padding-top: 15px;">
<svg @click="registrationParameters.splice(idx, 1)" style="cursor: pointer"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
</svg>

</td>
</tr>
</tbody>
</table>
</section>

<section>
<input type="button" class="btn btn-primary" value="Activate" @click="activate">
</section>
</div>
</template>

<script>
export default {
data() {
return {
fetchError: undefined,
discoveryServices: [],
selectedDiscoveryService: undefined,
registrationParameters: [],
}
},
mounted() {
this.$api.get('api/proxy/internal/discovery/v1')
.then(data => {
this.services = data
this.selectedDiscoveryService = this.services.filter(s => s.id === this.$route.params.discoveryServiceID)[0]
let registrationParametersInputDescriptors = this.selectedDiscoveryService.presentation_definition.input_descriptors.filter(descriptor => descriptor.constraints.fields.filter(f => f.filter && f.filter.type === "string" && f.filter.const === "DiscoveryRegistrationCredential").length > 0)
registrationParametersInputDescriptors.forEach(r => r.constraints.fields.filter(f => f.id && f.path)
.forEach(f => {
f.path.forEach(path => {
let label = f.id
if (f.purpose) {
label = "(" + label + ") " + f.purpose
}
// remove $.credentialSubject. from the beginning
const key = path.replace(/^\$\.credentialSubject\./, '')
this.registrationParameters.push({key: key, label: label})
})
})
)
})
.catch(response => {
this.fetchError = response.statusText
this.services = []
})
},
methods: {
updateStatus(event) {
this.$emit('statusUpdate', event)
},
activate() {
this.fetchError = undefined
let params = {}
this.registrationParameters.forEach(p => {
params[p.key] = p.value
})
this.$api.post(`api/proxy/internal/discovery/v1/${this.selectedDiscoveryService.id}/${this.$route.params.subjectID}`, {registrationParameters: params})
.then(data => {
if (data.reason) {
this.fetchError = data.reason
} else {
this.$router.push({name: 'admin.identityDetails', params: {subjectID: this.$route.params.subjectID}})
}
})
.catch(response => {
this.fetchError = response
})
}
}
}
</script>
17 changes: 1 addition & 16 deletions web/src/admin/IdentityDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<button v-if="service.active" class="btn btn-primary" @click="deactivateService(service.id)">
Deactivate
</button>
<button v-else class="btn btn-primary" @click="activateService(service.id)">
<button v-else class="btn btn-primary" @click="$router.push({name: 'admin.activateDiscoveryService', params: {subjectID: this.$route.params.subjectID, discoveryServiceID: service.id}})">
Activate
</button>
</td>
Expand Down Expand Up @@ -146,21 +146,6 @@ export default {
showDIDDocument(id) {
this.shownDIDDocument = this.shownDIDDocument === id ? undefined : id
},
activateService(id) {
this.fetchError = undefined
this.$api.post(`api/proxy/internal/discovery/v1/${id}/${this.details.subject}`)
.then(data => {
if (data.reason) {
this.fetchError = data.reason
}
})
.catch(response => {
this.fetchError = response
})
.finally(() => {
this.fetchData()
})
},
deactivateService(id) {
this.fetchError = undefined
this.$api.delete(`api/proxy/internal/discovery/v1/${id}/${this.details.subject}`)
Expand Down
12 changes: 9 additions & 3 deletions web/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import IssuedCredentials from './admin/IssuedCredentials.vue'
import Api from './plugins/api'
import IdentityDetails from "./admin/IdentityDetails.vue";
import IssueCredential from "./admin/IssueCredential.vue";
import ActivateDiscoveryService from "./admin/ActivateDiscoveryService.vue";

const routes = [
{
Expand All @@ -37,15 +38,20 @@ const routes = [
modal: NewIdentity
}
},
]
],
},
{
path: 'id/:subjectID',
name: 'admin.identityDetails',
component: IdentityDetails
component: IdentityDetails,
},
{
path: 'vc/issue/:credentialType?/:subjectDID?',
path: 'id/:subjectID/discovery/:discoveryServiceID/activate',
name: 'admin.activateDiscoveryService',
component: ActivateDiscoveryService
},
{
path: 'vc/issue/:credentialType?/:subjectDID',
name: 'admin.issueCredential',
component: IssueCredential
},
Expand Down

0 comments on commit 6bcc884

Please sign in to comment.