Skip to content
This repository has been archived by the owner on Sep 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1 from lca1/dev
Browse files Browse the repository at this point in the history
MedCo v0.2.0
  • Loading branch information
mickmis authored May 2, 2019
2 parents 5d66616 + d418769 commit 381eeca
Show file tree
Hide file tree
Showing 71 changed files with 4,875 additions and 1,047 deletions.
25 changes: 19 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
validate:
swagger validate ./swagger.yml
EXCLUDE_LINT = "_test.go"

gen: validate
# generate/update go server based on swagger specifications
swagger-gen:
swagger validate ./swagger/swagger.yml
swagger generate server \
--target=./ \
--spec=./swagger.yml \
--principal=models.User \
--target=./swagger/ \
--spec=./swagger/swagger.yml \
--name=medco-connector

.PHONY: install gen validate
test_lint:
@echo Checking linting of files
@{ \
go install golang.org/x/lint/golint; \
el=$(EXCLUDE_LINT); \
lintfiles=$$( golint ./... | egrep -v "$$el" ); \
if [ -n "$$lintfiles" ]; then \
echo "Lint errors:"; \
echo "$$lintfiles"; \
exit 1; \
fi \
}
38 changes: 38 additions & 0 deletions deployment/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM golang:1.11 as build

COPY ./ /src

# compile and install medco-connector
WORKDIR /src
RUN CGO_ENABLED=0 go build -v ./... && \
CGO_ENABLED=0 go install -v ./...

# -------------------------------------------
FROM golang:1.11-alpine as release

COPY deployment/docker-entrypoint.sh /usr/local/bin/
RUN apk update && apk add bash && rm -rf /var/cache/apk/* && \
chmod a+x /usr/local/bin/docker-entrypoint.sh

COPY --from=build /go/bin/medco-connector-server /go/bin/

# swagger server configuration
ENV HOST=0.0.0.0 \
PORT=1999

# run-time environment
ENV I2B2_HIVE_URL=http://i2b2:8080/i2b2/services \
I2B2_LOGIN_DOMAIN=i2b2medco \
I2B2_LOGIN_PROJECT=MedCo \
I2B2_LOGIN_USER=e2etest \
I2B2_LOGIN_PASSWORD=e2etest \
LOG_LEVEL=5 \
UNLYNX_GROUP_FILE_PATH=/medco-configuration/group.toml \
UNLYNX_GROUP_FILE_IDX=0 \
JWKS_URL=http://keycloak:8080/auth/realms/master/protocol/openid-connect/certs \
OIDC_JWT_ISSUER=http://keycloak:8080/auth/realms/master \
OIDC_CLIENT_ID=medco \
OIDC_JWT_USER_ID_CLAIM=preferred_username

EXPOSE 1999
ENTRYPOINT ["docker-entrypoint.sh"]
24 changes: 24 additions & 0 deletions deployment/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3.5'
services:
medco-connector:
image: medco/medco-connector:dev
build:
context: ../
dockerfile: deployment/Dockerfile
ports:
- "1999"
environment:
- I2B2_HIVE_URL=http://i2b2:8080/i2b2/services
- I2B2_LOGIN_DOMAIN=i2b2medco
- I2B2_LOGIN_PROJECT=MedCo
- I2B2_LOGIN_USER=e2etest
- I2B2_LOGIN_PASSWORD=e2etest
- LOG_LEVEL=5
- UNLYNX_GROUP_FILE_PATH=/medco-configuration/group.toml
- UNLYNX_GROUP_FILE_IDX=0
- JWKS_URL=http://keycloak:8080/auth/realms/master/protocol/openid-connect/certs
- OIDC_JWT_ISSUER=http://keycloak:8080/auth/realms/master
- OIDC_CLIENT_ID=medco
- OIDC_JWT_USER_ID_CLAIM=preferred_username
volumes:
- ./configuration-profile:/medco-configuration
10 changes: 10 additions & 0 deletions deployment/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -Eeuo pipefail

# trust the certificates of other nodes
if [[ `ls -1 /medco-configuration/srv*-certificate.crt 2>/dev/null | wc -l` != 0 ]]; then
/bin/cp -f /medco-configuration/srv*-certificate.crt /usr/local/share/ca-certificates/
update-ca-certificates
fi

exec medco-connector-server
16 changes: 15 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
module github.com/lca1/medco-connector

require (
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/go-openapi/analysis v0.18.0 // indirect
github.com/go-openapi/errors v0.18.0
github.com/go-openapi/jsonpointer v0.18.0 // indirect
github.com/go-openapi/jsonreference v0.18.0 // indirect
github.com/go-openapi/loads v0.18.0
github.com/go-openapi/runtime v0.18.0
github.com/go-openapi/spec v0.18.0
github.com/go-openapi/strfmt v0.18.0
github.com/go-openapi/swag v0.18.0
github.com/go-openapi/validate v0.18.0
github.com/google/uuid v1.1.1 // indirect
github.com/jessevdk/go-flags v1.4.0
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95
github.com/lca1/medco-unlynx v0.0.0-20190326092154-e12359adb567
github.com/lca1/unlynx v0.0.0-20190312131415-2e3533f65afe
github.com/lestrrat-go/jwx v0.0.0-20190415045601-bee008e7f2ee
github.com/lestrrat-go/pdebug v0.0.0-20180220043849-39f9a71bcabe // indirect
github.com/mailru/easyjson v0.0.0-20190221075403-6243d8e04c3f // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.0
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
go.dedis.ch/onet/v3 v3.0.0
golang.org/x/net v0.0.0-20190311183353-d8887717615a
)
119 changes: 112 additions & 7 deletions go.sum

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions i2b2/common_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package i2b2

import (
"encoding/xml"
"errors"
"github.com/lca1/medco-connector/util"
"strconv"
"time"
)

// NewRequest creates a new ready-to-use i2b2 request, with a nil message body
func NewRequest() Request {
now := time.Now()
return Request{
XMLNSMSG: "http://www.i2b2.org/xsd/hive/msg/1.1/",
XMLNSONT: "http://www.i2b2.org/xsd/cell/ont/1.1/",
XMLNSPDO: "http://www.i2b2.org/xsd/hive/pdo/1.1/",
XMLNSCRCPDO: "http://www.i2b2.org/xsd/cell/crc/pdo/1.1/",
XMLNSCRCPSM: "http://www.i2b2.org/xsd/cell/crc/psm/1.1/",

MessageHeader: MessageHeader{
I2b2VersionCompatible: "0.3",
Hl7VersionCompatible: "2.4",
SendingApplicationApplicationName: "MedCo Connector",
SendingApplicationApplicationVersion: "0.2",
SendingFacilityFacilityName: "MedCo",
ReceivingApplicationApplicationName: "i2b2 cell",
ReceivingApplicationApplicationVersion: "1.7",
ReceivingFacilityFacilityName: "i2b2 hive",
DatetimeOfMessage: now.Format(time.RFC3339),
SecurityDomain: util.I2b2LoginDomain,
SecurityUsername: util.I2b2LoginUser,
SecurityPassword: util.I2b2LoginPassword,
MessageTypeMessageCode: "EQQ",
MessageTypeEventType: "Q04",
MessageTypeMessageStructure: "EQQ_Q04",
MessageControlIDSessionID: now.Format(time.RFC3339),
MessageControlIDMessageNum: strconv.FormatInt(now.Unix(), 10),
MessageControlIDInstanceNum: "0",
ProcessingIDProcessingID: "P",
ProcessingIDProcessingMode: "I",
AcceptAcknowledgementType: "messageId",
ApplicationAcknowledgementType: "",
CountryCode: "CH",
ProjectID: util.I2b2LoginProject,
},
RequestHeader: RequestHeader{
ResultWaittimeMs: strconv.Itoa(util.I2b2TimeoutSeconds* 1000),
},
}
}

// NewRequestWithBody creates a new ready-to-use i2b2 request, with a message body
func NewRequestWithBody(body MessageBody) (req Request) {
req = NewRequest()
req.MessageBody = body
return
}

// Request is an i2b2 XML request
type Request struct {
XMLName xml.Name `xml:"msgns:request"`
XMLNSMSG string `xml:"xmlns:msgns,attr"`
XMLNSPDO string `xml:"xmlns:pdons,attr"`
XMLNSONT string `xml:"xmlns:ontns,attr"`
XMLNSCRCPDO string `xml:"xmlns:crcpdons,attr"`
XMLNSCRCPSM string `xml:"xmlns:crcpsmns,attr"`

MessageHeader MessageHeader `xml:"message_header"`
RequestHeader RequestHeader `xml:"request_header"`
MessageBody MessageBody `xml:"message_body"`
}

// Response is an i2b2 XML response
type Response struct {
XMLName xml.Name `xml:"response"`
MessageHeader MessageHeader `xml:"message_header"`
RequestHeader RequestHeader `xml:"request_header"`
ResponseHeader ResponseHeader `xml:"response_header"`
MessageBody MessageBody `xml:"message_body"`
}

func (response *Response) checkStatus() error {
if response.ResponseHeader.ResultStatus.Status.Type != "DONE" {
return errors.New(response.ResponseHeader.ResultStatus.Status.Text)
}
return nil
}

// MessageHeader is an i2b2 XML header embedded in a request or response
type MessageHeader struct {
XMLName xml.Name `xml:"message_header"`

I2b2VersionCompatible string `xml:"i2b2_version_compatible"`
Hl7VersionCompatible string `xml:"hl7_version_compatible"`

SendingApplicationApplicationName string `xml:"sending_application>application_name"`
SendingApplicationApplicationVersion string `xml:"sending_application>application_version"`

SendingFacilityFacilityName string `xml:"sending_facility>facility_name"`

ReceivingApplicationApplicationName string `xml:"receiving_application>application_name"`
ReceivingApplicationApplicationVersion string `xml:"receiving_application>application_version"`

ReceivingFacilityFacilityName string `xml:"receiving_facility>facility_name"`

DatetimeOfMessage string `xml:"datetime_of_message"`

SecurityDomain string `xml:"security>domain"`
SecurityUsername string `xml:"security>username"`
SecurityPassword string `xml:"security>password"`

MessageTypeMessageCode string `xml:"message_type>message_code"`
MessageTypeEventType string `xml:"message_type>event_type"`
MessageTypeMessageStructure string `xml:"message_type>message_structure"`

MessageControlIDSessionID string `xml:"message_control_id>session_id"`
MessageControlIDMessageNum string `xml:"message_control_id>message_num"`
MessageControlIDInstanceNum string `xml:"message_control_id>instance_num"`

ProcessingIDProcessingID string `xml:"processing_id>processing_id"`
ProcessingIDProcessingMode string `xml:"processing_id>processing_mode"`

AcceptAcknowledgementType string `xml:"accept_acknowledgement_type"`
ApplicationAcknowledgementType string `xml:"application_acknowledgement_type"`
CountryCode string `xml:"country_code"`
ProjectID string `xml:"project_id"`
}

// RequestHeader is an i2b2 XML header embedded in a request
type RequestHeader struct {
XMLName xml.Name `xml:"request_header"`
ResultWaittimeMs string `xml:"result_waittime_ms"`
}

// ResponseHeader is an i2b2 XML header embedded in a response
type ResponseHeader struct {
XMLName xml.Name `xml:"response_header"`
Info struct {
Text string `xml:",chardata"`
URL string `xml:"url,attr"`
} `xml:"info"`
ResultStatus struct {
Status struct {
Text string `xml:",chardata"`
Type string `xml:"type,attr"`
} `xml:"status"`
PollingURL struct {
Text string `xml:",chardata"`
IntervalMs string `xml:"interval_ms,attr"`
} `xml:"polling_url"`
Conditions struct {
Condition []struct {
Text string `xml:",chardata"`
Type string `xml:"type,attr"`
CodingSystem string `xml:"coding_system,attr"`
} `xml:"condition"`
} `xml:"conditions"`
} `xml:"result_status"`
}

// MessageBody is an i2b2 XML generic body
type MessageBody interface{}

50 changes: 50 additions & 0 deletions i2b2/common_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package i2b2

import (
"bytes"
"encoding/xml"
"github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
)

// todo doc
func i2b2XMLRequest(url string, xmlRequest interface{}, xmlResponse *Response) error {
logrus.Info("i2b2 XML request to " + url)

// marshal request
marshaledRequest, err := xml.MarshalIndent(xmlRequest, " ", " ")
if err != nil {
logrus.Error("error in i2b2 request marshalling:", err)
return err
}
marshaledRequest = append([]byte(xml.Header), marshaledRequest...)
logrus.Debug("i2b2 request:\n", string(marshaledRequest))

// execute HTTP request
httpResponse, err := http.Post(url, "application/xml", bytes.NewBuffer(marshaledRequest))
if err != nil {
logrus.Error("error in i2b2 request HTTP POST:", err)
return err
}
defer httpResponse.Body.Close()

// unmarshal response
httpBody, err := ioutil.ReadAll(httpResponse.Body)
logrus.Debug("i2b2 response:\n", string(httpBody))

err = xml.Unmarshal(httpBody, xmlResponse)
if err != nil {
logrus.Error("error in i2b2 response unmarshalling:", err)
return err
}

// check i2b2 request status
err = xmlResponse.checkStatus()
if err != nil {
logrus.Error("i2b2 error:", err)
return err
}

return nil
}
Loading

0 comments on commit 381eeca

Please sign in to comment.