Compare commits

...

12 Commits

  1. 5
      .dockerignore
  2. 5
      .gitignore
  3. 11
      Dockerfile.dvza
  4. 12
      Dockerfile.his
  5. 13
      Dockerfile.wbx
  6. 2
      cryptoutil/certgen.go
  7. 6
      docker-compose.yaml
  8. 2
      dvzaservice/app/src/Connection.js
  9. 2
      dvzaservice/app/src/Home.js
  10. 1
      dvzaservice/app/src/Registrations.js
  11. 25
      dvzaservice/main.go
  12. 4
      dvzaservice/model/db.go
  13. 12
      dvzaservice/openapisrv.go
  14. 7
      dvzaservice/srv.go
  15. 1
      dvzaservice/templates/index.html
  16. 6
      go.mod
  17. 4
      go.sum
  18. 2
      his/model/db.go
  19. 4
      his/model/models.go
  20. 11
      his/openapiclient.go
  21. 0
      his/patients/cbries.edi
  22. 0
      his/patients/cbries.fhir.json
  23. 0
      his/patients/jkorts.edi
  24. 0
      his/patients/jkorts.fhir.json
  25. 18
      his/srv.go
  26. 6
      sharedmodel/auth.go
  27. 2
      sharedmodel/model.go
  28. 6
      sharedmodel/registration.go
  29. 2
      sharedmodel/service.go
  30. 2
      whiteboxservice/app/src/Connection.js
  31. 2
      whiteboxservice/app/src/Home.js
  32. 1
      whiteboxservice/app/src/Registrations.js
  33. 0
      whiteboxservice/bin/amd64/ediviewer
  34. 0
      whiteboxservice/bin/amd64/medeur.json
  35. 0
      whiteboxservice/bin/amd64/template.html
  36. 0
      whiteboxservice/bin/arm64/ediviewer
  37. 0
      whiteboxservice/bin/arm64/medeur.json
  38. 300
      whiteboxservice/bin/arm64/template.html
  39. 31
      whiteboxservice/main.go
  40. 4
      whiteboxservice/model/db.go
  41. 30
      whiteboxservice/openapisrv.go
  42. 38
      whiteboxservice/srv.go
  43. 1
      whiteboxservice/templates/index.html

@ -1,4 +1,5 @@
**/.git **/.git
**/node_modules **/node_modules
**/app **/assets
**/data/data.db **/data/data.db
**/certs

5
.gitignore vendored

@ -1,3 +1,4 @@
node_modules node_modules
data/data.db data.db
certs certs
assets

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,16 +21,20 @@ WORKDIR /app/dvzaservice
RUN go build -o /app/bin/dvza RUN go build -o /app/bin/dvza
WORKDIR /app/dvzaservice/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./dvzaservice/assets /assets
COPY ./dvzaservice/templates /templates COPY ./dvzaservice/templates /templates
COPY --from=build /app/bin/dvza ./dvza COPY --from=build /app/bin/dvza ./dvza
COPY --from=build /app/dvzaservice/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,16 +21,21 @@ WORKDIR /app/his
RUN go build -o /app/bin/his RUN go build -o /app/bin/his
WORKDIR /app/his/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./his/assets /assets
COPY ./his/templates /templates COPY ./his/templates /templates
COPY ./his/patients /patients
COPY --from=build /app/bin/his ./his COPY --from=build /app/bin/his ./his
COPY --from=build /app/his/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,17 +21,21 @@ WORKDIR /app/whiteboxservice
RUN go build -o /app/bin/wbx RUN go build -o /app/bin/wbx
WORKDIR /app/whiteboxservice/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./whiteboxservice/assets /assets
COPY ./whiteboxservice/templates /templates COPY ./whiteboxservice/templates /templates
COPY ./whiteboxservice/bin /bin COPY ./whiteboxservice/bin/amd64 /wbxbin
COPY --from=build /app/bin/wbx ./wbx COPY --from=build /app/bin/wbx ./wbx
COPY --from=build /app/whiteboxservice/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -1,4 +1,4 @@
package certgen package cryptoutil
import ( import (
"bytes" "bytes"

@ -16,7 +16,7 @@ services:
container_name: okapi_wbx container_name: okapi_wbx
restart: always restart: always
environment: environment:
EXT_ADDR: "okapi_wbx:8888" EXT_ADDR: "okapi_wbx"
BIN_FOLDER: "/wbxbin" BIN_FOLDER: "/wbxbin"
volumes: volumes:
- "./wbx/data:/data" - "./wbx/data:/data"
@ -24,11 +24,11 @@ services:
ports: ports:
- 8085:8085 - 8085:8085
okapi_dvza: okapi_dvza:
image: src.whiteboxsystems.nl/decozo/okapidemo/whitebox image: src.whiteboxsystems.nl/decozo/okapidemo/dvza
container_name: okapi_dvza container_name: okapi_dvza
restart: always restart: always
environment: environment:
EXT_ADDR: "okapi_dvza:9999" EXT_ADDR: "okapi_dvza"
volumes: volumes:
- "./dvza/data:/data" - "./dvza/data:/data"
- "./dvza/certs:/certs" - "./dvza/certs:/certs"

@ -40,8 +40,6 @@ const Connection = () => {
useEffect(() => { useEffect(() => {
fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) ) fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) )
}, []) }, [])
console.log('connection', connection)
console.log('service', service)
return ( return (
<div> <div>
<h1 className="t-page-header">Verbinding</h1> <h1 className="t-page-header">Verbinding</h1>

@ -5,7 +5,7 @@ const App = () => {
return ( return (
<div> <div>
<h1 className="t-page-header">Welkom bij DVZA</h1> <h1 className="t-page-header">Welkom bij DVZA</h1>
<p>Dit systeem is beschikbaar op: <code>dvza.openkv.mcsr.nl:9999</code></p> <p>Dit systeem is beschikbaar op: <code>{window.externalUrl}</code></p>
</div> </div>
); );
}; };

@ -7,7 +7,6 @@ const App = () => {
useEffect(() => { useEffect(() => {
fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) ) fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) )
}, []) }, [])
console.log('registrations', registrations)
return ( return (
<div> <div>
<h1 className="t-page-header">Registratie verzoeken</h1> <h1 className="t-page-header">Registratie verzoeken</h1>

@ -12,18 +12,20 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
var rpcAddr = "0.0.0.0:9999" var rpcPort = "9999"
var rpcAddr = "0.0.0.0:" + rpcPort
var extRpcAddr = "localhost:" + rpcPort
var uiAddr = "0.0.0.0:9095" var uiAddr = "0.0.0.0:9095"
func loadCert() *tls.Certificate { func loadCert() *tls.Certificate {
_, err := os.Stat("certs/client.crt") _, err := os.Stat("certs/client.crt")
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("dvza", "dvza") _, _, certPem, keyPem, err := cryptoutil.GenCert("dvza", "dvza")
if err != nil { if err != nil {
panic(err) panic(err)
@ -53,20 +55,9 @@ func loadCert() *tls.Certificate {
func loadKeyPair() credentials.TransportCredentials { func loadKeyPair() credentials.TransportCredentials {
certificate := loadCert() certificate := loadCert()
// data, err := ioutil.ReadFile("certs/ca.crt")
// if err != nil {
// panic("failed to load CA file: " + err.Error())
// }
// capool := x509.NewCertPool()
// if !capool.AppendCertsFromPEM(data) {
// panic("can't add ca cert")
// }
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -84,6 +75,10 @@ func main() {
grpcServer := grpc.NewServer(opts...) grpcServer := grpc.NewServer(opts...)
if ext := os.Getenv("EXT_ADDR"); ext != "" {
extRpcAddr = ext + ":" + rpcPort
}
go func() { go func() {
lis, err := net.Listen("tcp", rpcAddr) lis, err := net.Listen("tcp", rpcAddr)
if err != nil { if err != nil {

@ -4,8 +4,8 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -13,10 +13,10 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/dvzaservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/dvzaservice/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
var errNotAuthorized = fmt.Errorf("Not Authorized") var errNotAuthorized = fmt.Errorf("Not Authorized")
@ -59,7 +59,7 @@ func requireConnection(db *gorm.DB, ctx context.Context) (*sharedmodel.Connectio
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
log.Println("request certificate subject:", item.Subject) log.Println("request certificate subject:", item.Subject)
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -240,7 +240,7 @@ func (srv *OkAPIServer) CompleteRegistration(
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }

@ -10,8 +10,8 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapidemo/dvzaservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/dvzaservice/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
type UIService struct { type UIService struct {
@ -69,7 +69,8 @@ func (srv *UIService) init() {
} }
func (srv *UIService) GetIndex(c *gin.Context) { func (srv *UIService) GetIndex(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{})
c.HTML(http.StatusOK, "index.html", gin.H{"externalURL": extRpcAddr})
} }
func (srv *UIService) GetConnection(c *gin.Context) { func (srv *UIService) GetConnection(c *gin.Context) {

@ -8,6 +8,7 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script>window.externalUrl = '{{.externalURL}}'</script>
<script src="/assets/js/index.js"></script> <script src="/assets/js/index.js"></script>
</body> </body>
</html> </html>

@ -1,14 +1,16 @@
module src.whiteboxsystems.nl/DECOZO/okapidemo module src.whiteboxsystems.nl/decozo/okapidemo
go 1.18 go 1.18
require ( require (
github.com/gin-gonic/gin v1.8.1 github.com/gin-gonic/gin v1.8.1
github.com/gofrs/uuid v4.2.0+incompatible github.com/gofrs/uuid v4.2.0+incompatible
github.com/lestrrat-go/jwx v1.2.25
google.golang.org/grpc v1.48.0 google.golang.org/grpc v1.48.0
google.golang.org/protobuf v1.28.0 google.golang.org/protobuf v1.28.0
gorm.io/driver/sqlite v1.3.6 gorm.io/driver/sqlite v1.3.6
gorm.io/gorm v1.23.8 gorm.io/gorm v1.23.8
src.whiteboxsystems.nl/decozo/okapi v0.0.5
) )
require ( require (
@ -27,7 +29,6 @@ require (
github.com/lestrrat-go/blackmagic v1.0.0 // indirect github.com/lestrrat-go/blackmagic v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.1 // indirect github.com/lestrrat-go/iter v1.0.1 // indirect
github.com/lestrrat-go/jwx v1.2.25 // indirect
github.com/lestrrat-go/option v1.0.0 // indirect github.com/lestrrat-go/option v1.0.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect github.com/mattn/go-sqlite3 v1.14.12 // indirect
@ -42,5 +43,4 @@ require (
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4 // indirect
) )

@ -229,5 +229,5 @@ gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4 h1:Hn/zWj14zknYYQr2rxkpwgZxpE+lH/qqeBp2RL9A/xY= src.whiteboxsystems.nl/decozo/okapi v0.0.5 h1:iAvxdLSib7M8+LwOufPa1rF5usufzG0Vv2qWp2gjzi0=
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4/go.mod h1:zzd5uxSJdsWDyIu2LOpyBLme9Nvo6GaXsbd1CL7BmDU= src.whiteboxsystems.nl/decozo/okapi v0.0.5/go.mod h1:NTi+fO+ZkB01CVZlCDPiyWjbxEfaiPS2ECBPmu/XWek=

@ -4,7 +4,7 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -4,8 +4,8 @@ import (
"time" "time"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
type ConnectionState string type ConnectionState string

@ -11,10 +11,10 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/his/model" "src.whiteboxsystems.nl/decozo/okapidemo/his/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func toStruct(m map[string]interface{}) *structpb.Struct { func toStruct(m map[string]interface{}) *structpb.Struct {
@ -40,7 +40,6 @@ func getUnauthenticatedClient(addr string) (okapi.OkAPIClient, error) {
return nil, err return nil, err
} }
// defer serviceProvider.Close()
return okapi.NewOkAPIClient(conn), nil return okapi.NewOkAPIClient(conn), nil
} }
@ -88,7 +87,7 @@ func (srv *HISServer) register(addr string) (*model.ServiceProvider, error) {
return nil, err return nil, err
} }
jwkBytes, err := certgen.PublicKeyToJWKJson(certgen.ExtractPublicKey(srv.clientCert.PrivateKey)) jwkBytes, err := cryptoutil.PublicKeyToJWKJson(cryptoutil.ExtractPublicKey(srv.clientCert.PrivateKey))
if err != nil { if err != nil {
return nil, err return nil, err

@ -18,17 +18,17 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/his/model" "src.whiteboxsystems.nl/decozo/okapidemo/his/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func loadCert() *tls.Certificate { func loadCert() *tls.Certificate {
_, err := os.Stat("certs/client.crt") _, err := os.Stat("certs/client.crt")
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("whitebox", "whitebox") _, _, certPem, keyPem, err := cryptoutil.GenCert("whitebox", "whitebox")
if err != nil { if err != nil {
panic(err) panic(err)
@ -61,7 +61,6 @@ func loadKeyPair() credentials.TransportCredentials {
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -265,8 +264,9 @@ func (srv *HISServer) Authenticate(c *gin.Context) {
raw := "" raw := ""
method := "" method := ""
if len(c.Request.TLS.PeerCertificates) > 0 { if len(c.Request.TLS.PeerCertificates) > 0 {
jwk, err := certgen.PublicKeyToJWK(c.Request.TLS.PeerCertificates[0].PublicKey) jwk, err := cryptoutil.PublicKeyToJWK(c.Request.TLS.PeerCertificates[0].PublicKey)
if err != nil { if err != nil {
log.Printf("Error extracting public key JKW: %v", err) log.Printf("Error extracting public key JKW: %v", err)
@ -568,7 +568,7 @@ func (srv *HISServer) GetPatient(c *gin.Context) {
return return
} }
f, err := os.Open(path.Join("./data/patients", patient.FileBase+".edi")) f, err := os.Open(path.Join("./patients", patient.FileBase+".edi"))
if err != nil { if err != nil {
c.Error(err) c.Error(err)
return return
@ -599,7 +599,7 @@ func (srv *HISServer) GetFHIRPatient(c *gin.Context) {
return return
} }
f, err := os.Open(path.Join("./data/patients", patient.FileBase+".fhir.json")) f, err := os.Open(path.Join("./patients", patient.FileBase+".fhir.json"))
if err != nil { if err != nil {
c.Error(err) c.Error(err)
return return

@ -6,8 +6,8 @@ import (
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
const AuthMethodDecozoMTLS = "http://decozo.org/proto/auth/mtls" const AuthMethodDecozoMTLS = "http://decozo.org/proto/auth/mtls"
@ -56,7 +56,7 @@ func NewAuthConfig(cfg *okapi.ProtocolAuthConfiguration) *AuthConfig {
authConfig.Raw, _ = cfg.GetConfiguration().AsMap()["token"].(string) authConfig.Raw, _ = cfg.GetConfiguration().AsMap()["token"].(string)
case AuthMethodDecozoMTLS: case AuthMethodDecozoMTLS:
k, _ := cfg.GetConfiguration().AsMap()["publicKey"].(string) k, _ := cfg.GetConfiguration().AsMap()["publicKey"].(string)
jwk, _ := certgen.StringToJWK(k) jwk, _ := cryptoutil.StringToJWK(k)
if jwk != nil { if jwk != nil {
rawBytes, _ := jwk.Thumbprint(crypto.SHA256) rawBytes, _ := jwk.Thumbprint(crypto.SHA256)
authConfig.Raw = fmt.Sprintf("%X", rawBytes) authConfig.Raw = fmt.Sprintf("%X", rawBytes)

@ -6,7 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
) )
type Protocol struct { type Protocol struct {

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
type RegistrationStatus string type RegistrationStatus string
@ -35,7 +35,7 @@ func (r *Registration) SetAuthConfig(cfg *okapi.XISAuthConfiguration) error {
switch cfg.Method { switch cfg.Method {
case okapi.XISAuthMethod_mTLS: case okapi.XISAuthMethod_mTLS:
k, err := certgen.StringToJWK(cfg.GetMtlsConfiguration().GetPublicKey()) k, err := cryptoutil.StringToJWK(cfg.GetMtlsConfiguration().GetPublicKey())
if err != nil { if err != nil {
return err return err

@ -5,7 +5,7 @@ import (
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
) )
type ServiceDefinition struct { type ServiceDefinition struct {

@ -40,8 +40,6 @@ const Connection = () => {
useEffect(() => { useEffect(() => {
fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) ) fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) )
}, []) }, [])
console.log('connection', connection)
console.log('service', service)
return ( return (
<div> <div>
<h1 className="t-page-header">Patiënten</h1> <h1 className="t-page-header">Patiënten</h1>

@ -5,7 +5,7 @@ const App = () => {
return ( return (
<div> <div>
<h1 className="t-page-header">Welkom bij Whitebox</h1> <h1 className="t-page-header">Welkom bij Whitebox</h1>
<p>Dit systeem is beschikbaar op: <code>wbx.openkv.mcsr.nl:8888</code></p> <p>Dit systeem is beschikbaar op: <code>{window.externalUrl}</code></p>
</div> </div>
); );
}; };

@ -7,7 +7,6 @@ const App = () => {
useEffect(() => { useEffect(() => {
fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) ) fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) )
}, []) }, [])
console.log('registrations', registrations)
return ( return (
<div> <div>
<h1 className="t-page-header">Registratie verzoeken</h1> <h1 className="t-page-header">Registratie verzoeken</h1>

@ -1,103 +1,98 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>{{.Patient.Name}} — MEDEUR</title>
<style> <style>
body { margin: 1em auto; font-size: 12pt; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; } .container { margin: 1em auto; font-size: 12pt; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; }
@media screen and (max-width: 700px) { @media screen and (max-width: 700px) {
body { width: 700px; } .container { width: 700px; }
} }
@media screen and (min-width: 1200px) { @media screen and (min-width: 1200px) {
body { width: 1200px; } .container { width: 1200px; }
} }
* { margin: 0; padding: 0; box-sizing: border-box; } .container h3 { margin-bottom: 8px; }
h3 { margin-bottom: 8px; } .container ul { list-style-type: none; }
ul { list-style-type: none; } .container li + li { margin-top: 10px; }
li + li { margin-top: 10px; } .container td { vertical-align: top; }
td { vertical-align: top; } .container .seg { margin-top: 8px; padding: 8px 10px; border: 0 solid #e7e7e7; border-width: 0 1px 1px 1px; }
.seg { margin-top: 8px; padding: 8px 10px; border: 0 solid #e7e7e7; border-width: 0 1px 1px 1px; } .container .seg-hdr { margin-top: 8px; border-top-width: 1px; background: #F8F8F8; }
.seg-hdr { margin-top: 8px; border-top-width: 1px; background: #F8F8F8; } .container .seg-hdr-white { margin-top: 8px; background: #FFFFFF; border-color: transparent; }
.seg-hdr-white { margin-top: 8px; background: #FFFFFF; border-color: transparent; }
.container a { color: royalblue }
a { color: royalblue }
.container table.patient th { text-align: left; padding-right: 1em }
table.patient th { text-align: left; padding-right: 1em }
.container table.SOEPkind { margin: -6px 0 }
table.SOEPkind { margin: -6px 0 } .container table.SOEPkind tr { height: 1em }
table.SOEPkind tr { height: 1em } .container table.SOEPkind th { text-align: left; width: 32px; height: 1em; font-weight: normal }
table.SOEPkind th { text-align: left; width: 32px; height: 1em; font-weight: normal }
.container table.results th { text-align: left }
table.results th { text-align: left }
.container .error { position: fixed; top: 10px; margin-left: 32px; border: 2px solid #000000; background-color: #FF2222; }
.error { position: fixed; top: 10px; margin-left: 32px; border: 2px solid #000000; background-color: #FF2222; }
.row + .row { margin-top: 4px; }
.row + .row { margin-top: 4px; }
.table { font-size: 100%; width: 100%; border-spacing: 0; border-collapse: collapse; }
.table { font-size: 100%; width: 100%; border-spacing: 0; border-collapse: collapse; } .table tr { font-size: 100% }
.table tr { font-size: 100% } .table td { font-size: 100% }
.table td { font-size: 100% } .table th { font-size: 100%; text-align: left; }
.table th { font-size: 100%; text-align: left; } .table tbody td { font-size: 100%; text-align: left; padding: 2px 8px 2px 0; }
.table tbody td { font-size: 100%; text-align: left; padding: 2px 8px 2px 0; } .table thead th { font-size: 100%; padding: 0 0 2px 0; }
.table thead th { font-size: 100%; padding: 0 0 2px 0; } .table tr.highlight { background: #E3E9E3 }
.table tr.highlight { background: #E3E9E3 }
.column-attn { width: 1em; }
.column-attn { width: 1em; } .column-code { width: 4em; }
.column-code { width: 4em; } .column-date { width: 6.5em; }
.column-date { width: 6.5em; } .column-small-name { width: 10em; }
.column-small-name { width: 10em; } .column-medium-name { width: 14em; }
.column-medium-name { width: 14em; } .column-large-name { width: 28em; }
.column-large-name { width: 28em; } .column-name { width: 20em; }
.column-name { width: 20em; } .column-instr{ width: 15em; }
.column-instr{ width: 15em; } .column-quantity { width: 12em; }
.column-quantity { width: 12em; }
.no-margin { margin-bottom: 0px; }
.no-margin { margin-bottom: 0px; }
.seg-date { float: left; width: 6.5em; }
.seg-date { float: left; width: 6.5em; } .seg-content-offset { margin-left: 6.5em }
.seg-content-offset { margin-left: 6.5em }
.column-result-id { width: 16em }
.column-result-id { width: 16em } .column-result-name { width: 10em }
.column-result-name { width: 10em }
.container h3.fold-toggle { margin-bottom: 8px }
h3.fold-toggle { margin-bottom: 8px } .container h4.fold-toggle { margin-bottom: 0; margin-top: 4px }
h4.fold-toggle { margin-bottom: 0; margin-top: 4px } .container h3.fold-toggle.fold-toggle-hidden { margin-bottom: 0 }
h3.fold-toggle.fold-toggle-hidden { margin-bottom: 0 } .container h4.fold-toggle.fold-toggle-hidden { margin-bottom: 4px }
h4.fold-toggle.fold-toggle-hidden { margin-bottom: 4px } .fold-toggle .fold-marker:before,
.fold-toggle .fold-marker:before, .container h3.fold-toggle:before,
h3.fold-toggle:before, .container h4.fold-toggle:before { content: "▾ " }
h4.fold-toggle:before { content: "▾ " } .fold-toggle.fold-toggle-hidden .fold-marker:before,
.fold-toggle.fold-toggle-hidden .fold-marker:before, .container h3.fold-toggle.fold-toggle-hidden:before,
h3.fold-toggle.fold-toggle-hidden:before, .container h4.fold-toggle.fold-toggle-hidden:before { content: "▸ " }
h4.fold-toggle.fold-toggle-hidden:before { content: "▸ " } .fold-toggle { cursor: pointer; }
.fold-toggle { cursor: pointer; } .fold-hidden {display: none}
.fold-hidden {display: none}
.hidden
.hidden {
{ display: none !important
display: none !important }
}
textarea .container textarea
{ {
border: 1px solid #333; border: 1px solid #333;
padding: .5em; padding: .5em;
font-size: 100% font-size: 100%
} }
input[type=submit] .container input[type=submit]
{ {
font-size: 90%; font-size: 90%;
padding: .25em padding: .25em
} }
button .container button
{ {
font-size: 75%; font-size: 75%;
padding: .25em padding: .25em
} }
</style></head> </style>
<body>
<div class="container"> <div class="container">
{{define "person-row"}} {{define "person-row"}}
@ -114,9 +109,6 @@ button
<thead> <thead>
<tr> <tr>
<th class="column-date">Datum</th> <th class="column-date">Datum</th>
{{if HasEndDates .Episodes }}
<th class="column-date">Einddatum</th>
{{end}}
<th class="column-code">Type</th> <th class="column-code">Type</th>
<th class="column-date">ICPC</th> <th class="column-date">ICPC</th>
<th class="column-name">Beschrijving</th> <th class="column-name">Beschrijving</th>
@ -128,32 +120,26 @@ button
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{range .Episodes}} {{range .Episodes}}
<tr {{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}> <tr{{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}>
<td>{{.Date}}</td> <td>{{.Date}}</td>
<td>{{.Type}}</td>
{{if HasEndDates $.Episodes }} <td>{{.ICPC}}</td>
<td style="{{if EndDateInPast .EndDate}}color: red;{{end}}">{{.EndDate}}</td>
{{end}}
<td>{{.Type}}</td> {{if eq $root.Extra.verbose_icpc_description "true"}}
<td>{{.ICPC}}</td> <td>{{.Title}}</td>
<td>{{.Description}}</td>
{{if eq $root.Extra.verbose_icpc_description "true"}} {{else}}
<td>{{.Title}}</td> {{if eq .Description ""}}
<td>{{.Description}}</td> <td colspan="2">{{.Title}}</td>
{{else}} {{else}}
{{if eq .Description ""}} <td colspan="2">{{.Description}}</td>
<td colspan="2">{{.Title}}</td> {{end}}
{{else}} {{end}}
<td colspan="2">{{.Description}}</td> </tr>{{end}}
{{end}}
{{end}}
</tr>
{{end}}
</tbody> </tbody>
</table> </table>
{{end}} {{end}}
{{define "medi-group-ica"}} {{define "medi-group-ica"}}
{{$root := .}} {{$root := .}}
@ -244,7 +230,7 @@ button
{{if .Episodes}} {{if .Episodes}}
<div class="seg seg-hdr"> <div class="seg seg-hdr">
<h3>Episodelijst</h3> <h3>Episodelijst</h3>
{{template "medi-group-epi" .}} {{template "medi-group-epi" .}}
</div> </div>
{{end}} {{end}}
@ -363,14 +349,14 @@ button
{{if .Extra.csrf_token }} {{if .Extra.csrf_token }}
<div class="seg seg-hdr-white"> <div class="seg seg-hdr-white">
<br> <br>
<h3 id="feedback-header"><button onClick="feedbackHeaderClicked()">Notitie schrijven</button></h3> <h3 id="feedback-header"><button onClick="feedbackHeaderClicked()">Notitie schrijven</button></h3>
<form id="feedback-form" class="hidden" method="POST" onSubmit="sendFeedback(); return false"> <!-- TODO: contruct proper URL in golang --> <form id="feedback-form" class="hidden" method="POST" onSubmit="sendFeedback(); return false"> <!-- TODO: contruct proper URL in golang -->
<input type="hidden" name="csrf_token" value="{{.Extra.csrf_token}}" id="csrf"> <input type="hidden" name="csrf_token" value="{{.Extra.csrf_token}}" id="csrf">
<p><br><textarea id="feedback-textarea" rows="7" cols="50"></textarea> <p><br><textarea id="feedback-textarea" rows="7" cols="50"></textarea>
<p><br><input type="submit" value="Opsturen"> <p><br><input type="submit" value="Opsturen">
</form> </form>
</div> </div>
@ -453,68 +439,4 @@ function getXMLHttpRequest()
} }
} }
function sendFeedback()
{
var URL = document.location.href.replace('preview', '') + 'pushback'
var textarea = document.getElementById('feedback-textarea')
var message = textarea.value
var csrf_element = document.getElementById('csrf')
var csrf= csrf_element.value
var xmlhttp = getXMLHttpRequest()
xmlhttp.onreadystatechange = function() { sendFeedbackHandler(xmlhttp) }
params = '';
params += 'csrf_token=' + encodeURIComponent(csrf) + '&'
params += 'message=' + encodeURIComponent(message)
xmlhttp.open('POST', URL, true)
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xmlhttp.setRequestHeader('Content-length', params.length)
xmlhttp.setRequestHeader('Connection', 'close')
xmlhttp.send(params)
}
function sendFeedbackHandler(xmlhttp)
{
if (xmlhttp.readyState != 4) { return }
if (xmlhttp.status == 200)
{
try
{
var response = JSON.parse(xmlhttp.responseText)
if (response.success) {
alert('Feedback is succesvol verstuurd.')
toggle('feedback-form')
} else {
alert('Er is iets fout gegaan: ' + response.error)
}
}
catch (e)
{
alert('Fout bij versturen feedback.')
}
}
else
{
alert('Fout bij versturen feedback.')
}
}
function send_height_to_parent() {
var body = document.body,
html = document.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
var msg = {
"height": height,
};
parent.postMessage(msg, "*");
}
send_height_to_parent();
</script></body></html> </script></body></html>

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
@ -12,19 +13,22 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
var srvaddr = "0.0.0.0:8888" var rpcPort = "8888"
var srvaddr = "0.0.0.0:" + rpcPort
var extRpcAddr = "localhost:" + rpcPort
var patientIf = "0.0.0.0:8085" var patientIf = "0.0.0.0:8085"
var binFolder = "./bin"
func loadCert() *tls.Certificate { var binFolder = "./bin/arm64"
_, err := os.Stat("certs/client.crt")
func loadCert(name string) *tls.Certificate {
_, err := os.Stat(fmt.Sprintf("certs/%s.crt", name))
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("whitebox", "whitebox") _, _, certPem, keyPem, err := cryptoutil.GenCert("whitebox", "whitebox")
if err != nil { if err != nil {
panic(err) panic(err)
@ -34,15 +38,15 @@ func loadCert() *tls.Certificate {
panic(err) panic(err)
} }
if err := ioutil.WriteFile("certs/client.crt", []byte(certPem), 0600); err != nil { if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.crt", name), []byte(certPem), 0600); err != nil {
panic(err) panic(err)
} }
if err := ioutil.WriteFile("certs/client.key", []byte(keyPem), 0600); err != nil { if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.key", name), []byte(keyPem), 0600); err != nil {
panic(err) panic(err)
} }
} }
certificate, err := tls.LoadX509KeyPair("certs/client.crt", "certs/client.key") certificate, err := tls.LoadX509KeyPair(fmt.Sprintf("certs/%s.crt", name), fmt.Sprintf("certs/%s.key", name))
if err != nil { if err != nil {
panic("Load client certification failed: " + err.Error()) panic("Load client certification failed: " + err.Error())
@ -52,12 +56,11 @@ func loadCert() *tls.Certificate {
} }
func loadKeyPair() credentials.TransportCredentials { func loadKeyPair() credentials.TransportCredentials {
certificate := loadCert() certificate := loadCert("client")
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -71,6 +74,10 @@ func main() {
binFolder = os.Getenv("BIN_FOLDER") binFolder = os.Getenv("BIN_FOLDER")
} }
if ext := os.Getenv("EXT_ADDR"); ext != "" {
extRpcAddr = ext + ":" + rpcPort
}
openapisrv := NewServer() openapisrv := NewServer()
openapisrv.LoadData("./data/data.db") openapisrv.LoadData("./data/data.db")
opts := []grpc.ServerOption{ opts := []grpc.ServerOption{

@ -4,8 +4,8 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -14,10 +14,10 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
"src.whiteboxsystems.nl/DECOZO/okapidemo/whiteboxservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/whiteboxservice/model"
) )
var errNotAuthorized = fmt.Errorf("Not Authorized") var errNotAuthorized = fmt.Errorf("Not Authorized")
@ -45,6 +45,8 @@ type OkAPIServer struct {
okapi.UnimplementedOkAPIServer okapi.UnimplementedOkAPIServer
data *gorm.DB data *gorm.DB
clientCert tls.Certificate clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
} }
func (srv *OkAPIServer) LoadData(location string) error { func (srv *OkAPIServer) LoadData(location string) error {
@ -61,7 +63,7 @@ func requireConnection(db *gorm.DB, ctx context.Context) (*sharedmodel.Connectio
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
log.Println("request certificate subject:", item.Subject) log.Println("request certificate subject:", item.Subject)
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -224,7 +226,7 @@ func (srv *OkAPIServer) CompleteRegistration(
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -307,7 +309,15 @@ func (srv *OkAPIServer) EnableService(
AuthConfig: sharedmodel.NewAuthConfig(in.Fetch.Auth), AuthConfig: sharedmodel.NewAuthConfig(in.Fetch.Auth),
} }
publicKey, err := certgen.PublicKeyToJWKJson(certgen.ExtractPublicKey(srv.clientCert.PrivateKey)) var cert tls.Certificate
if in.ServiceId == "wbx:visitelijst" {
cert = srv.visiteCert
} else if in.ServiceId == "wbx:waarneming" {
cert = srv.wnhCert
}
publicKey, err := cryptoutil.PublicKeyToJWKJson(cryptoutil.ExtractPublicKey(cert.PrivateKey))
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retrieving pub key: %v", err) return nil, fmt.Errorf("Error retrieving pub key: %v", err)
@ -621,9 +631,13 @@ func (srv *OkAPIServer) ListPatientRegistrations(
} }
func NewServer() *OkAPIServer { func NewServer() *OkAPIServer {
cert := loadCert() cert := loadCert("client")
visiteCert := loadCert("visite")
wnhCert := loadCert("wnh")
return &OkAPIServer{ return &OkAPIServer{
clientCert: *cert, clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
} }
} }

@ -13,14 +13,16 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
"src.whiteboxsystems.nl/DECOZO/okapidemo/whiteboxservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/whiteboxservice/model"
) )
type UIService struct { type UIService struct {
srv *http.Server srv *http.Server
inited bool inited bool
clientCert tls.Certificate clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
data *gorm.DB data *gorm.DB
} }
@ -70,7 +72,7 @@ func (srv *UIService) init() {
} }
func (srv *UIService) GetIndex(c *gin.Context) { func (srv *UIService) GetIndex(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{}) c.HTML(http.StatusOK, "index.html", gin.H{"externalURL": extRpcAddr})
} }
func (srv *UIService) GetConnection(c *gin.Context) { func (srv *UIService) GetConnection(c *gin.Context) {
@ -117,14 +119,21 @@ func (srv *UIService) GetPatient(c *gin.Context) {
} }
url := fmt.Sprintf("%v/%v/%v", protoconfig["url"], "patients", protometa["patientID"]) url := fmt.Sprintf("%v/%v/%v", protoconfig["url"], "patients", protometa["patientID"])
req, _ := http.NewRequest("GET", url, nil) req, _ := http.NewRequest("GET", url, nil)
var cert tls.Certificate
if serviceConfig.Service.ServiceID == "wbx:visitelijst" {
cert = srv.visiteCert
} else if serviceConfig.Service.ServiceID == "wbx:waarneming" {
cert = srv.wnhCert
}
client := &http.Client{ client := &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
Certificates: []tls.Certificate{srv.clientCert}, Certificates: []tls.Certificate{cert},
}, },
}, },
} }
@ -224,12 +233,19 @@ func (srv *UIService) GetRegistrations(c *gin.Context) {
} }
func NewUIServer(addr string) *UIService { func NewUIServer(addr string) *UIService {
cert := loadCert() cert := loadCert("client")
visiteCert := loadCert("visite")
srv := &UIService{srv: &http.Server{ wnhCert := loadCert("wnh")
Addr: addr,
Handler: gin.Default(), srv := &UIService{
}, clientCert: *cert} srv: &http.Server{
Addr: addr,
Handler: gin.Default(),
},
clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
}
return srv return srv
} }

@ -8,6 +8,7 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script>window.externalUrl = '{{.externalURL}}'</script>
<script src="/assets/js/index.js"></script> <script src="/assets/js/index.js"></script>
</body> </body>
</html> </html>
Loading…
Cancel
Save