Compare commits

..

10 Commits

Author SHA1 Message Date
Bas Kloosterman a39ce2266c dvza make external addr possible, rebase 1 year ago
Bas Kloosterman 9769156ae8 Remove js output 1 year ago
Bas Kloosterman 0b93d9afa6 Fix docker compose 1 year ago
Bas Kloosterman ab4df72651 Update ignore files 1 year ago
Bas Kloosterman cc2483fa7b Rename certgen -> cryptoutil 1 year ago
Bas Kloosterman 63fc98966a Update module name end dependencies, change case 1 year ago
Bas Kloosterman 003069969c Add different versions of ediviewer (amd64|arm64) 1 year ago
Bas Kloosterman c3a5d3c808 Rebase move patients 1 year ago
Bas Kloosterman 4ad2117208 Make external grpc address configurable 1 year ago
Bas Kloosterman f06ff5fd0e Move patients 1 year ago
  1. 2
      dvzaservice/app/src/Connection.js
  2. 1
      dvzaservice/app/src/Registrations.js
  3. 11
      dvzaservice/main.go
  4. BIN
      extbin/ediviewer
  5. 1
      extbin/medeur.json
  6. 520
      extbin/template.html
  7. 1
      his/openapiclient.go
  8. 2
      his/srv.go
  9. 2
      whiteboxservice/app/src/Connection.js
  10. 1
      whiteboxservice/app/src/Registrations.js
  11. 14
      whiteboxservice/main.go
  12. 18
      whiteboxservice/openapisrv.go
  13. 32
      whiteboxservice/srv.go

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

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

@ -55,9 +55,20 @@ func loadCert() *tls.Certificate {
func loadKeyPair() credentials.TransportCredentials {
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{
ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
}
return credentials.NewTLS(tlsConfig)
}

Binary file not shown.

@ -0,0 +1 @@
{"format":[{"name":"UNB","description":"Interchange header"},{"name":"UNH","description":"Head of message"},{"name":"BGM","children":[{"name":"DTM","description":"Datum aangemaakt"},{"name":"RFF","description":"Referenties"},{"name":"FTX","description":"Bericht afhankelijke mededeling"}],"description":"Begin van het bericht"},{"name":"S01","children":[{"name":"NAD","description":"Naam en adres"},{"name":"ADR","description":"Adres"},{"name":"COM","description":"Telefoon- en fax-nummers"},{"name":"RFF"},{"name":"DTM"},{"name":"LAN"},{"name":"SPR","description":"Type medewerker"},{"name":"QUA","description":"Kwalificatie"},{"name":"FTX","description":"Vrije tekst"}],"description":"Medebehandelaar"},{"name":"S02","children":[{"name":"PNA","description":"Naam van de patient"},{"name":"ADR","description":"Adres-patient"},{"name":"COM","description":"Telefoon- en fax-nummers"},{"name":"RFF","description":"Referenties"},{"name":"DTM","description":"Tijdsindicatie"},{"name":"NAT"},{"name":"LAN"},{"name":"LOC"},{"name":"PDI","description":"Demografische gegevens"},{"name":"QUA","description":"Kwalificatie"},{"name":"STS"},{"name":"INS","description":"Verzekeringsgegevens"},{"name":"REL"},{"name":"FTX","description":"Vrije tekst"},{"name":"S03","children":[{"name":"DTM","description":"Tijdsindicatie"},{"name":"S04","children":[{"name":"CIN","description":"Diagnose signalering of risico-factor"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Referentie naar groep 1"},{"name":"FTX","description":"Vrije tekst"},{"name":"DTM","description":"Tijdsindicatie"}],"description":"Medisch kenmerk"},{"name":"S05","children":[{"name":"INV"},{"name":"DTM"}]}],"description":"Contact onafhankelijke medische gegevens"},{"name":"S06","children":[{"name":"DTM","description":"Datum/tijd van een contact"},{"name":"RFF","description":"Verantwoordelijke persoon"},{"name":"S07","children":[{"name":"FTX"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Probleem/episode"},{"name":"DTM","description":"Datum/tijd van een contact"}],"description":"Ongeclassificeerde journaalregel"},{"name":"S08","children":[{"name":"INV","description":"Meting identificatie"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Probleem/episode"},{"name":"RSL","description":"Resultaat meting"},{"name":"RND","description":"Normaalwaarden"},{"name":"FTX","description":"Resultaat"},{"name":"DTM","description":"Datum/tijd"}],"description":"Metingen"},{"name":"S09","children":[{"name":"CIN","description":"Diagnose"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Probleem/episode"},{"name":"FTX","description":"Diagnose in vrije tekst"},{"name":"DTM","description":"Datum/tijd"}],"description":"Diagnoses"},{"name":"S10","children":[{"name":"SPR","description":"Specialisme"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Probleem/episode"},{"name":"PRC","description":"Soort verwijzing"},{"name":"FTX","description":"Beschrijving"},{"name":"DTM","description":"Datum/tijd"}],"description":"Verwijzingen of terugverwijzingen"},{"name":"S11","children":[{"name":"CLI","description":"Type therapie"},{"name":"PTY","description":"Prioriteit"},{"name":"RFF","description":"Probleem/episode"},{"name":"FTX","description":"Vrije tekst"},{"name":"QTY","description":"Hoeveelheid"},{"name":"DNL","children":[{"name":"DSG","description":"Dose administration"},{"name":"FTX","description":"Vrije tekst"}],"description":"Dosering Nederlandse stijl"},{"name":"SPC","children":[{"name":"QTY","description":"Hoeveelheid"}],"description":"Afzonderlijke stoffen van recept"},{"name":"CIN","description":"Indicatie"},{"name":"SPR","description":"Specialisme voorschrijver"},{"name":"DTM","description":"Datum/tijd"}],"description":"Therapie"}],"description":"Journaalregel"}],"description":"Pati\u00ebnt"},{"name":"UNT","description":"Einde van het bericht"},{"name":"UNZ","description":"Einde uitwisseling"}]}

@ -0,0 +1,520 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>{{.Patient.Name}} — MEDEUR</title>
<style>
body { margin: 1em auto; font-size: 12pt; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; }
@media screen and (max-width: 700px) {
body { width: 700px; }
}
@media screen and (min-width: 1200px) {
body { width: 1200px; }
}
* { margin: 0; padding: 0; box-sizing: border-box; }
h3 { margin-bottom: 8px; }
ul { list-style-type: none; }
li + li { margin-top: 10px; }
td { vertical-align: top; }
.seg { margin-top: 8px; padding: 8px 10px; border: 0 solid #e7e7e7; border-width: 0 1px 1px 1px; }
.seg-hdr { margin-top: 8px; border-top-width: 1px; background: #F8F8F8; }
.seg-hdr-white { margin-top: 8px; background: #FFFFFF; border-color: transparent; }
a { color: royalblue }
table.patient th { text-align: left; padding-right: 1em }
table.SOEPkind { margin: -6px 0 }
table.SOEPkind tr { height: 1em }
table.SOEPkind th { text-align: left; width: 32px; height: 1em; font-weight: normal }
table.results th { text-align: left }
.error { position: fixed; top: 10px; margin-left: 32px; border: 2px solid #000000; background-color: #FF2222; }
.row + .row { margin-top: 4px; }
.table { font-size: 100%; width: 100%; border-spacing: 0; border-collapse: collapse; }
.table tr { font-size: 100% }
.table td { font-size: 100% }
.table th { font-size: 100%; text-align: left; }
.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 tr.highlight { background: #E3E9E3 }
.column-attn { width: 1em; }
.column-code { width: 4em; }
.column-date { width: 6.5em; }
.column-small-name { width: 10em; }
.column-medium-name { width: 14em; }
.column-large-name { width: 28em; }
.column-name { width: 20em; }
.column-instr{ width: 15em; }
.column-quantity { width: 12em; }
.no-margin { margin-bottom: 0px; }
.seg-date { float: left; width: 6.5em; }
.seg-content-offset { margin-left: 6.5em }
.column-result-id { width: 16em }
.column-result-name { width: 10em }
h3.fold-toggle { margin-bottom: 8px }
h4.fold-toggle { margin-bottom: 0; margin-top: 4px }
h3.fold-toggle.fold-toggle-hidden { margin-bottom: 0 }
h4.fold-toggle.fold-toggle-hidden { margin-bottom: 4px }
.fold-toggle .fold-marker:before,
h3.fold-toggle:before,
h4.fold-toggle:before { content: "▾ " }
.fold-toggle.fold-toggle-hidden .fold-marker:before,
h3.fold-toggle.fold-toggle-hidden:before,
h4.fold-toggle.fold-toggle-hidden:before { content: "▸ " }
.fold-toggle { cursor: pointer; }
.fold-hidden {display: none}
.hidden
{
display: none !important
}
textarea
{
border: 1px solid #333;
padding: .5em;
font-size: 100%
}
input[type=submit]
{
font-size: 90%;
padding: .25em
}
button
{
font-size: 75%;
padding: .25em
}
</style></head>
<body>
<div class="container">
{{define "person-row"}}
<tr id="person-{{.Anchor}}">
<td class="column-small-name">{{if .Name}}{{.Name}}{{else}}<em>Geen naam</em>{{end}}</td>
<td class="column-small-name">{{.Function}}</td>
<td class="column-medium-name">{{.Address}}</td>
<td class="column-small-name">{{if .AGB}}AGB: {{.AGB}}{{end}}</td>
</tr>{{end}}
{{define "medi-group-epi"}}
{{$root := .}}
<table class="table">
<thead>
<tr>
<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-date">ICPC</th>
<th class="column-name">Beschrijving</th>
{{if eq .Extra.verbose_icpc_description "true"}}
<th class="column-desc">Beschrijving arts</th>
{{else}}
{{end}}
<th class="column-desc"></th>
</tr>
</thead>
<tbody>
{{range .Episodes}}
<tr {{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}>
<td>{{.Date}}</td>
{{if HasEndDates $.Episodes }}
<td style="{{if EndDateInPast .EndDate}}color: red;{{end}}">{{.EndDate}}</td>
{{end}}
<td>{{.Type}}</td>
<td>{{.ICPC}}</td>
{{if eq $root.Extra.verbose_icpc_description "true"}}
<td>{{.Title}}</td>
<td>{{.Description}}</td>
{{else}}
{{if eq .Description ""}}
<td colspan="2">{{.Title}}</td>
{{else}}
<td colspan="2">{{.Description}}</td>
{{end}}
{{end}}
</tr>
{{end}}
</tbody>
</table>
{{end}}
{{define "medi-group-ica"}}
{{$root := .}}
<table class="table">
<thead>
<tr>
<th class="column-date">Datum</th>
<th class="column-code">Type</th>
<th class="column-date">ICPC</th>
<th class="column-name" colspan="2">Beschrijving</th>
{{if eq $root.Extra.verbose_icpc_description "true"}}
<th class="column-desc"></th>
{{else}}
{{end}}
</tr>
</thead>
<tbody>
{{range .Indicators}}
<tr{{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}>
<td>{{.Date}}</td>
<td>{{.Type}}</td>
<td>{{.ICPC}}</td>
<td>{{.Title}}</td>
{{if eq $root.Extra.verbose_icpc_description "true"}}
<td>{{.Description}}</td>
{{else}}
<td></td>
{{end}}
</tr>{{end}}
</tbody>
</table>
{{end}}
<div class="seg seg-hdr" data-his="{{.HIS}}">
<h3>Huisarts</h3>
<table class="table">
{{template "person-row" .GP}}
{{if .Pharmacy.Anchor}}{{template "person-row" .Pharmacy}}{{end}}
</table>
{{if .Practitioners}}
<h4 data-fold-toggle="practicioners" data-fold-hide="1">Medebehandelaren</h4>
<div data-fold="practicioners">
<table class="table">{{range .Practitioners}}
{{template "person-row" .}}{{end}}
</table>
</div>
{{end}}
</div>
<div class="seg seg-hdr">
<h3>Patiënt</h3>
<table class="patient">
<tr>
<th>Naam:
<td>{{.Patient.Name}}
{{if .Patient.BSN}}
<tr>
<th>BSN:
<td>{{.Patient.BSN}}
{{end}}
<tr>
<th>Geboortedatum:
<td>{{.Patient.Birthdate}}
<tr>
<th>Adres:
<td>{{.Patient.Address}}
<tr>
<th>Geslacht:
<td>{{.Patient.Gender}}
{{range .Patient.OtherFields}}
<tr>
<th>{{.Key}}:
<td{{if eq .Key "Toegepast filter"}} title="Een filter is een (standaard) filter dat door een huisarts over alle of een deel van de patiëntendossiers wordt toegepast. De minimale professionele samenvatting (PS) bevat een samenvatting van alleen zeer recente informatie uit het huisartsdossier, met alleen actuele / chronische medicatie. Dit is minder informatie dan de standaard NHG PS, die journaalregels tot 4 maanden terug, of de laatste 5 consultverslagen kan bevatten. Houd er svp rekening mee dat geen enkel type PS alle, of gegarandeerd volledige of correcte informatie bevat."{{end}}>{{.Value}}
{{end}}
</table>
</div>
{{if .Memo}}
<div class="seg seg-hdr">
<h3>Memo</h3>
{{.Memo}}
</div>
{{end}}
{{if .Episodes}}
<div class="seg seg-hdr">
<h3>Episodelijst</h3>
{{template "medi-group-epi" .}}
</div>
{{end}}
{{if .Indicators}}
<div class="seg seg-hdr">
<h3>Contra-indicaties, interacties en allergie&#235;n</h3>
{{template "medi-group-ica" .}}
</div>
{{end}}
{{if .Medication}}
<div class="seg seg-hdr">
<h3 data-fold-toggle="med-table">Medicatieoverzicht</h3>
<table data-fold="med-table" class="table">
<thead>
<tr>
<th class="column-large-name">Recept</th>
<th class="column-instr">Gebruiksvoorschrift</th>
<th class="column-quantity">Hoeveelheid</th>
<th class="column-date">Ingang</th>
<th class="column-date">Vervalt</th>
</tr>
</thead>
<tbody>
{{range $index, $med := .Medication}}
{{if gt (len $med.Fold) 1}}
<tr data-fold-toggle="medfold-{{$index}}" data-fold-hide="1">
<td>{{$med.Recipe}}</td>
<td>{{$med.Instructions}}</td>
<td>{{ YieldDosage $med }}</td>
<td>{{$med.StartDate}}</td>
<td>{{$med.EndDate}}</td>
</tr>
{{range $fold := $med.Fold}}
<tr data-fold="medfold-{{$index}}">
<td></td>
<td>{{ if ne $med.Instructions $fold.Instructions}}{{$fold.Instructions}}{{else}}{{end}}</td>
<td>{{ YieldDosage $fold }}</td>
<td>{{$fold.StartDate}}</td>
<td>{{$fold.EndDate}}</td>
</tr>
{{end}}
{{else}}
<tr>
<td>{{$med.Recipe}}</td>
<td>{{$med.Instructions}}</td>
<td>{{ YieldDosage $med }}</td>
<td>{{$med.StartDate}}</td>
<td>{{$med.EndDate}}</td>
</tr>
{{end}}
{{end }}
</tbody>
</table>
</div>
{{end}}
{{if .Journal}}
<div class="seg seg-hdr-white">
<h3>Journaal</h3>
</div>
{{range .Journal}}
<div class="seg seg-hdr">
<div class="seg-date">{{.Date}}</div>
<div class="seg-content-offset" title="{{.AuthorName}}{{if .Kind}} ({{.Kind}}){{end}}">
{{if .Results}}
<div class="row">
<table class="results">
<thead>
<tr>
<th class="column-result-id">Identificatie</th>
<th class="column-result-name">Resultaat</th>
<th class="column-result-desc">Beschrijving</th>
</tr>
</thead>
<tbody>
{{range .Results}}
<tr {{if .Episode}}data-episode="{{.Episode}}"{{end}}><td>{{.Kind}}</td>
<td>{{.Result}}</td>
<td>{{if eq .Identification "Buiten normaalwaarde"}}<strong>{{.Identification}}</strong>{{else}}{{.Identification}}{{end}}
{{if and .Identification .Description}}<br>{{end}}
{{.Description}}
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
{{end}}
{{range .Lines}}
<div class="row"{{if .Episode}} data-episode="{{.Episode}}"{{end}}>
<table class="SOEPkind">
<tr>
{{if .SOEP}}
<th style="padding-top: 10px; vertical-align: top;">{{.SOEP}}:
<td style="padding-top: 10px; vertical-align: top;">{{ConvertLinebreaks .Text}}
{{end}}
{{if .Kind}}
<th style="padding-top: 10px; vertical-align: top;">{{.Kind}}{{if .Text}}:{{end}}
<td style="padding-top: 10px; vertical-align: top;">{{ConvertLinebreaks .Text}}
{{end}}
</tr>
</table>
</div>
{{end}}
</div>
</div>
{{end}}
{{end}}
{{if .Extra.csrf_token }}
<div class="seg seg-hdr-white">
<br>
<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 -->
<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><input type="submit" value="Opsturen">
</form>
</div>
{{end}}
</div>
<script>
(function() {
var folds = document.querySelectorAll('[data-fold-toggle]');
for (var i = 0; i < folds.length; i++) {
(function(btn) {
var t = btn.getAttribute('data-fold-toggle');
var fds = document.querySelectorAll('[data-fold="' + t + '"]');
btn.classList.add('fold-toggle');
var hidden = false;
var sync = function() {
if (hidden) {
btn.classList.add('fold-toggle-hidden');
} else {
btn.classList.remove('fold-toggle-hidden');
}
for (var j = 0; j < fds.length; j++) {
var e = fds[j].classList;
if (hidden) {
e.add('fold-hidden');
} else {
e.remove('fold-hidden');
}
}
setTimeout(send_height_to_parent, 0);
};
if (btn.getAttribute('data-fold-hide') == '1') {
hidden = true;
}
btn.addEventListener('click', function() {
hidden = !hidden;
sync();
});
sync();
})(folds[i]);
}
})();
function feedbackHeaderClicked()
{
toggle('feedback-form')
var textarea = document.getElementById('feedback-textarea')
textarea.focus()
}
function toggle(id)
{
var elem = document.getElementById(id)
if (elem)
{
var className = elem.getAttribute('class')
if (className == 'hidden')
{
elem.setAttribute('class', '')
}
else
{
elem.setAttribute('class', 'hidden')
}
}
}
function getXMLHttpRequest()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
return new ActiveXObject('Microsoft.XMLHTTP')
}
}
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>

@ -40,6 +40,7 @@ func getUnauthenticatedClient(addr string) (okapi.OkAPIClient, error) {
return nil, err
}
// defer serviceProvider.Close()
return okapi.NewOkAPIClient(conn), nil
}

@ -61,6 +61,7 @@ func loadKeyPair() credentials.TransportCredentials {
tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
}
return credentials.NewTLS(tlsConfig)
}
@ -264,7 +265,6 @@ func (srv *HISServer) Authenticate(c *gin.Context) {
raw := ""
method := ""
if len(c.Request.TLS.PeerCertificates) > 0 {
jwk, err := cryptoutil.PublicKeyToJWK(c.Request.TLS.PeerCertificates[0].PublicKey)

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

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

@ -3,7 +3,6 @@ package main
import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
"log"
"net"
@ -24,8 +23,8 @@ var patientIf = "0.0.0.0:8085"
var binFolder = "./bin/arm64"
func loadCert(name string) *tls.Certificate {
_, err := os.Stat(fmt.Sprintf("certs/%s.crt", name))
func loadCert() *tls.Certificate {
_, err := os.Stat("certs/client.crt")
if err != nil {
_, _, certPem, keyPem, err := cryptoutil.GenCert("whitebox", "whitebox")
@ -38,15 +37,15 @@ func loadCert(name string) *tls.Certificate {
panic(err)
}
if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.crt", name), []byte(certPem), 0600); err != nil {
if err := ioutil.WriteFile("certs/client.crt", []byte(certPem), 0600); err != nil {
panic(err)
}
if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.key", name), []byte(keyPem), 0600); err != nil {
if err := ioutil.WriteFile("certs/client.key", []byte(keyPem), 0600); err != nil {
panic(err)
}
}
certificate, err := tls.LoadX509KeyPair(fmt.Sprintf("certs/%s.crt", name), fmt.Sprintf("certs/%s.key", name))
certificate, err := tls.LoadX509KeyPair("certs/client.crt", "certs/client.key")
if err != nil {
panic("Load client certification failed: " + err.Error())
@ -56,11 +55,12 @@ func loadCert(name string) *tls.Certificate {
}
func loadKeyPair() credentials.TransportCredentials {
certificate := loadCert("client")
certificate := loadCert()
tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
}
return credentials.NewTLS(tlsConfig)
}

@ -45,8 +45,6 @@ type OkAPIServer struct {
okapi.UnimplementedOkAPIServer
data *gorm.DB
clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
}
func (srv *OkAPIServer) LoadData(location string) error {
@ -309,15 +307,7 @@ func (srv *OkAPIServer) EnableService(
AuthConfig: sharedmodel.NewAuthConfig(in.Fetch.Auth),
}
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))
publicKey, err := cryptoutil.PublicKeyToJWKJson(cryptoutil.ExtractPublicKey(srv.clientCert.PrivateKey))
if err != nil {
return nil, fmt.Errorf("Error retrieving pub key: %v", err)
@ -631,13 +621,9 @@ func (srv *OkAPIServer) ListPatientRegistrations(
}
func NewServer() *OkAPIServer {
cert := loadCert("client")
visiteCert := loadCert("visite")
wnhCert := loadCert("wnh")
cert := loadCert()
return &OkAPIServer{
clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
}
}

@ -21,8 +21,6 @@ type UIService struct {
srv *http.Server
inited bool
clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
data *gorm.DB
}
@ -119,21 +117,14 @@ func (srv *UIService) GetPatient(c *gin.Context) {
}
url := fmt.Sprintf("%v/%v/%v", protoconfig["url"], "patients", protometa["patientID"])
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
}
req, _ := http.NewRequest("GET", url, nil)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{cert},
Certificates: []tls.Certificate{srv.clientCert},
},
},
}
@ -233,19 +224,12 @@ func (srv *UIService) GetRegistrations(c *gin.Context) {
}
func NewUIServer(addr string) *UIService {
cert := loadCert("client")
visiteCert := loadCert("visite")
wnhCert := loadCert("wnh")
srv := &UIService{
srv: &http.Server{
Addr: addr,
Handler: gin.Default(),
},
clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
}
cert := loadCert()
srv := &UIService{srv: &http.Server{
Addr: addr,
Handler: gin.Default(),
}, clientCert: *cert}
return srv
}

Loading…
Cancel
Save