Skip to content

Commit

Permalink
Support HomeMonitoring use case
Browse files Browse the repository at this point in the history
  • Loading branch information
reinkrul committed Mar 28, 2024
1 parent 978cc23 commit 1f435d2
Show file tree
Hide file tree
Showing 32 changed files with 3,173 additions and 1,375 deletions.
36 changes: 36 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.PHONY: dev

run-generators: gen-api

install-tools:
go install github.com/deepmap/oapi-codegen/v2/cmd/[email protected]

gen-api:
npm run gen-api

oapi-codegen -generate types -package types -o domain/types/generated_types.go api/api.yaml
oapi-codegen -generate server -package api -o api/generated.go api/api.yaml
oapi-codegen -generate client,types -package auth \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/auth/generated.go https://nuts-node.readthedocs.io/en/latest/_static/auth/v1.yaml
oapi-codegen -generate client,types -package common -exclude-schemas VerifiableCredential,VerifiablePresentation,DID,DIDDocument -generate types,skip-prune -o nuts/client/common/generated.go https://nuts-node.readthedocs.io/en/latest/_static/common/ssi_types.yaml
oapi-codegen -generate client,types -package discovery \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-exclude-schemas SearchVCRequest,CredentialSubject \
-o nuts/client/discovery/generated.go https://nuts-node.readthedocs.io/en/latest/_static/discovery/v1.yaml
oapi-codegen -generate client,types -package vcr \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-exclude-schemas SearchVCRequest,CredentialSubject \
-o nuts/client/vcr/generated.go https://nuts-node.readthedocs.io/en/latest/_static/vcr/vcr_v2.yaml
oapi-codegen -generate client,types -package didman \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/didman/generated.go -exclude-schemas OrganizationSearchResult https://nuts-node.readthedocs.io/en/latest/_static/didman/v1.yaml
oapi-codegen -generate client,types -package vdr \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/vdr/generated.go https://nuts-node.readthedocs.io/en/latest/_static/vdr/v1.yaml
oapi-codegen -generate client,types -package vdr_v2 \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/vdr_v2/generated.go https://nuts-node.readthedocs.io/en/latest/_static/vdr/v2.yaml
oapi-codegen -generate client,types -package iam \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/iam/generated.go https://nuts-node.readthedocs.io/en/latest/_static/auth/iam.yaml
25 changes: 1 addition & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,7 @@ go run . live

The API and domain types are generated from the `api/api.yaml`.
```shell
npm run gen-api

oapi-codegen -generate types -package types -o domain/types/generated_types.go api/api.yaml
oapi-codegen -generate server -package api -o api/generated.go api/api.yaml
oapi-codegen -generate client,types -package auth \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/auth/generated.go https://nuts-node.readthedocs.io/en/latest/_static/auth/v1.yaml
oapi-codegen -generate client,types -package discovery \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/discovery/generated.go https://nuts-node.readthedocs.io/en/latest/_static/discovery/v1.yaml
oapi-codegen -generate client,types -package iam \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/iam/generated.go https://nuts-node.readthedocs.io/en/latest/_static/auth/iam.yaml
oapi-codegen -generate client,types -package common -exclude-schemas VerifiableCredential,VerifiablePresentation,DID,DIDDocument -generate types,skip-prune -o nuts/client/common/generated.go https://nuts-node.readthedocs.io/en/latest/_static/common/ssi_types.yaml
oapi-codegen -generate client,types -package vcr \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-exclude-schemas SearchVCRequest,CredentialSubject \
-o nuts/client/vcr/generated.go https://nuts-node.readthedocs.io/en/latest/_static/vcr/vcr_v2.yaml
oapi-codegen -generate client,types -package didman \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/didman/generated.go -exclude-schemas OrganizationSearchResult https://nuts-node.readthedocs.io/en/latest/_static/didman/v1.yaml
oapi-codegen -generate client,types -package vdr \
-import-mapping='../common/ssi_types.yaml:github.com/nuts-foundation/nuts-demo-ehr/nuts/client/common' \
-o nuts/client/vdr/generated.go https://nuts-node.readthedocs.io/en/latest/_static/vdr/v1.yaml
make gen-api
```

### Docker
Expand Down
20 changes: 20 additions & 0 deletions api/acl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package api

import (
"github.com/labstack/echo/v4"
"net/http"
)

func (w Wrapper) GetACL(ctx echo.Context, tenantDID string, authorizedDID string) error {
authorizedResources, err := w.ACL.AuthorizedResources(ctx.Request().Context(), tenantDID, authorizedDID)
if err != nil {
return err
}

result := make(map[string][]string)
for _, resource := range authorizedResources {
result[resource.Resource] = append(result[resource.Resource], resource.Operation)
}

return ctx.JSON(http.StatusOK, result)
}
26 changes: 14 additions & 12 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package api
import (
"encoding/json"
"fmt"
"github.com/nuts-foundation/nuts-demo-ehr/domain"
"github.com/nuts-foundation/nuts-demo-ehr/domain/acl"
"github.com/nuts-foundation/nuts-demo-ehr/domain/fhir"
"net/http"
"strconv"
Expand Down Expand Up @@ -41,9 +43,8 @@ var _ ServerInterface = (*Wrapper)(nil)

type Wrapper struct {
APIAuth *Auth
NutsAuth nutsClient.Auth
NutsIam nutsClient.Iam
NutsDiscovery nutsClient.Discovery
ACL *acl.Repository
NutsClient *nutsClient.HTTPClient
CustomerRepository customers.Repository
PatientRepository patients.Repository
ReportRepository reports.Repository
Expand All @@ -53,6 +54,7 @@ type Wrapper struct {
TransferSenderService sender.TransferService
TransferReceiverService receiver.TransferService
TransferReceiverRepo receiver.TransferRepository
ZorginzageService domain.ZorginzageService
FHIRService fhir.Service
EpisodeService episode.Service
NotificationHandler notification.Handler
Expand Down Expand Up @@ -115,7 +117,7 @@ func (w Wrapper) CreateAuthorizationRequest(ctx echo.Context) error {
if err != nil {
return ctx.JSON(http.StatusInternalServerError, errorResponse{err})
}
response, err := w.NutsIam.CreateAuthenticationRequest(*customer.Did)
response, err := w.NutsClient.CreateAuthenticationRequest(*customer.Did)
if err != nil {
return err
}
Expand All @@ -133,7 +135,7 @@ func (w Wrapper) GetOpenID4VPAuthenticationResult(ctx echo.Context, token string
//if err != nil {
// return ctx.JSON(http.StatusInternalServerError, errorResponse{err})
//}
response, err := w.NutsIam.GetAuthenticationResult(token)
response, err := w.NutsClient.GetAuthenticationResult(token)
if err != nil {
return err
}
Expand All @@ -153,7 +155,7 @@ func (w Wrapper) AuthenticateWithIRMA(ctx echo.Context) error {
}

// forward to node
bytes, err := w.NutsAuth.CreateIrmaSession(*customer.Did)
bytes, err := w.NutsClient.CreateIrmaSession(*customer.Did)
if err != nil {
return err
}
Expand All @@ -171,7 +173,7 @@ func (w Wrapper) GetIRMAAuthenticationResult(ctx echo.Context, sessionToken stri
}

// forward to node
sessionStatus, err := w.NutsAuth.GetIrmaSessionResult(sessionToken)
sessionStatus, err := w.NutsClient.GetIrmaSessionResult(sessionToken)
if err != nil {
return err
}
Expand All @@ -183,7 +185,7 @@ func (w Wrapper) GetIRMAAuthenticationResult(ctx echo.Context, sessionToken stri
authSessionID, err := w.getSessionID(ctx)
if err != nil {
// No current session, create a new one. Introspect IRMA VP and extract properties for UserInfo.
userPresentation, err := w.NutsAuth.VerifyPresentation(*sessionStatus.VerifiablePresentation)
userPresentation, err := w.NutsClient.VerifyPresentation(*sessionStatus.VerifiablePresentation)
if err != nil {
return fmt.Errorf("unable to verify presentation: %w", err)
}
Expand Down Expand Up @@ -245,7 +247,7 @@ func (w Wrapper) AuthenticateWithEmployeeID(ctx echo.Context) error {
"familyName": session.UserInfo.FamilyName,
},
}
bytes, err := w.NutsAuth.CreateEmployeeIDSession(params)
bytes, err := w.NutsClient.CreateEmployeeIDSession(params)
if err != nil {
return err
}
Expand All @@ -268,7 +270,7 @@ func (w Wrapper) GetEmployeeIDAuthenticationResult(ctx echo.Context, sessionToke
authSessionID, _ := w.getSessionID(ctx) // can't fail

// forward to node
sessionStatus, err := w.NutsAuth.GetEmployeeIDSessionResult(sessionToken)
sessionStatus, err := w.NutsClient.GetEmployeeIDSessionResult(sessionToken)
if err != nil {
return err
}
Expand Down Expand Up @@ -306,7 +308,7 @@ func (w Wrapper) AuthenticateWithDummy(ctx echo.Context) error {
return ctx.JSON(http.StatusInternalServerError, errorResponse{err})
}

bytes, err := w.NutsAuth.CreateDummySession(*customer.Did)
bytes, err := w.NutsClient.CreateDummySession(*customer.Did)
if err != nil {
return err
}
Expand Down Expand Up @@ -338,7 +340,7 @@ func (w Wrapper) GetDummyAuthenticationResult(ctx echo.Context, sessionToken str
// for dummy, it takes a few request to get to status completed.
for i := 0; i < 4; i++ {
// forward to node
sessionResult, err = w.NutsAuth.GetDummySessionResult(sessionToken)
sessionResult, err = w.NutsClient.GetDummySessionResult(sessionToken)
if err != nil {
return err
}
Expand Down
150 changes: 119 additions & 31 deletions api/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -592,41 +592,86 @@ paths:
schema:
$ref: "#/components/schemas/Patient"

/private/network/organizations:
get:
/private/network/discovery:
# Search has become a POST instead of GET, since it uses an object (query) as input,
# which OpenAPI Codegenerator does not handle properly for GET operations.
post:
description: Searches for other care organizations on Nuts Network.
operationId: searchOrganizations
parameters:
- name: query
in: query
description: Keyword for finding care organizations.
required: true
schema:
type: string
- name: didServiceType
in: query
description: >
Filters other care organizations on the Nuts Network on service, only returning care organizations have a service in their DID Document which' type matches the given didServiceType and not including your own.
If not supplied, care organizations aren't filtered on service.
required: false
schema:
type: string
- name: discoveryServiceType
in: query
description: >
Filters other care organizations on the Nuts Network on service, only returning care organizations that registered for the given service at a discovery server.
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- query
properties:
query:
type: object
additionalProperties:
type: string
description: >
The search query, key-value string properties. E.g.:
'credentialSubject.organization.name: Ziekenhuis'
discoveryServiceID:
description: >
Filters other care organizations on the Nuts Network, only returning care organizations that registered for the given Discovery Service.
It false, it will search on all Discovery Services.
type: string
didServiceType:
description: >
Filters other care organizations on the Nuts Network on service, only returning care organizations have a service in their DID Document which' type matches the given didServiceType and not including your own.
If not supplied, care organizations aren't filtered on service.
type: string
excludeOwn:
description: >
If true, the current care organization is excluded from the search results.
Defaults to false.
type: boolean
responses:
200:
description: Search successful.
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Organization"
type: object
additionalProperties:
type: array
items:
type: object

/private/network/patient:
parameters:
- name: patientSSN
in: query
description: The patient's SSN
required: true
schema:
type: string
- name: remotePartyDID
in: query
description: The DID of the remote party.
required: true
schema:
type: string
- name: scope
in: query
description: The OAuth2 scope to request.
required: true
schema:
type: string
get:
description: Load the medical records of a patient at a remote XIS.
operationId: getRemotePatient
responses:
200:
description: The patient's medical records from the remote XIS.
content:
application/json:
schema:
$ref: "#/components/schemas/Patient"


/private/network/inbox:
get:
Expand Down Expand Up @@ -693,11 +738,8 @@ paths:
schema:
$ref: "#/components/schemas/Report"
responses:
200:
204:
description: The creation of the new report is completed
content:
applaction/json:
schema:
/private/dossier/{patientID}:
get:
description: Get list of dossiers for a patient
Expand Down Expand Up @@ -754,6 +796,45 @@ paths:
204:
description: Notification processed successfully.

/internal/acl/{tenantDID}/{authorizedDID}:
parameters:
- name: tenantDID
in: path
description: The DID of the tenant who owns the resources
required: true
content:
plain/text:
schema:
type: string
example: did:web:example.com
- name: authorizedDID
in: path
description: The DID of the authorized party
required: true
content:
plain/text:
schema:
type: string
example: did:web:example.com
get:
description: |
Get all resource/operation combinations the authorized party was granted access to by the tenant.
When a collaboration is initiated in the application, it registers the related FHIR resources on the ACL.
The Policy Decision Point (PDP) can then use this ACL to make authorization decisions.
An example consumer of this endpoint is Open Policy Agent using http.send()
operationId: getACL
responses:
200:
description: The ACL for the tenant and authorized party
content:
application/json:
schema:
type: object
additionalProperties:
type: array
items:
type: string
/internal/customer/{customerID}/task/{taskID}:
parameters:
- name: customerID
Expand Down Expand Up @@ -951,6 +1032,7 @@ components:
- name
- city
- did
- discoveryServices
properties:
name:
description: Name of the care organization.
Expand All @@ -961,6 +1043,12 @@ components:
did:
description: Decentralized Identifier which uniquely identifies the care organization on the Nuts Network.
type: string
discoveryServices:
description: >
List of Discovery Services the care organization is registered with.
type: array
items:
type: string
CreateTransferNegotiationRequest:
description: An request object to create a new transfer negotiation.
type: object
Expand Down
Loading

0 comments on commit 1f435d2

Please sign in to comment.