You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.3 KiB
251 lines
6.3 KiB
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"sync"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
"src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
|
|
"src.whiteboxsystems.nl/decozo/okapidemo/whiteboxservice/model"
|
|
)
|
|
|
|
type UIService struct {
|
|
srv *http.Server
|
|
inited bool
|
|
clientCert tls.Certificate
|
|
visiteCert tls.Certificate
|
|
wnhCert tls.Certificate
|
|
data *gorm.DB
|
|
}
|
|
|
|
func (srv *UIService) LoadData(location string) error {
|
|
var err error
|
|
srv.data, err = model.GetDB(location)
|
|
return err
|
|
}
|
|
|
|
func (srv *UIService) Addr() string {
|
|
if srv.srv == nil {
|
|
return ""
|
|
}
|
|
return srv.srv.Addr
|
|
}
|
|
|
|
func (srv *UIService) ListenAndServe() error {
|
|
if !srv.inited {
|
|
srv.init()
|
|
}
|
|
log.Printf("Listening on %v\n", srv.srv.Addr)
|
|
return srv.srv.ListenAndServe()
|
|
}
|
|
|
|
func (srv *UIService) Shutdown(ctx context.Context) error {
|
|
return srv.srv.Shutdown(ctx)
|
|
}
|
|
|
|
func (srv *UIService) init() {
|
|
r := srv.srv.Handler.(*gin.Engine)
|
|
|
|
r.LoadHTMLGlob("templates/*")
|
|
r.Static("/assets", "./assets")
|
|
|
|
r.Use(srv.Authenticate)
|
|
r.GET("/", func(c *gin.Context) {
|
|
c.Redirect(http.StatusMovedPermanently, "/ui")
|
|
})
|
|
r.GET("/ui", srv.GetIndex)
|
|
r.GET("/ui/*page", srv.GetIndex)
|
|
r.GET("/api/connections", srv.GetConnections)
|
|
r.GET("/api/connections/:connID", srv.GetConnection)
|
|
r.GET("/api/connections/:connID/:serviceID", srv.GetSubscriptions)
|
|
r.GET("/api/connections/:connID/:serviceID/:patientID", srv.GetPatient)
|
|
r.GET("/api/registrations", srv.GetRegistrations)
|
|
srv.inited = true
|
|
}
|
|
|
|
func (srv *UIService) GetIndex(c *gin.Context) {
|
|
c.HTML(http.StatusOK, "index.html", gin.H{"externalURL": extRpcAddr})
|
|
}
|
|
|
|
func (srv *UIService) GetConnection(c *gin.Context) {
|
|
connID := c.Param("connID")
|
|
connection := &sharedmodel.Connection{}
|
|
srv.data.Where("id = ?", connID).Find(&connection)
|
|
c.JSON(http.StatusOK, connection)
|
|
}
|
|
func (srv *UIService) GetSubscriptions(c *gin.Context) {
|
|
connID := c.Param("connID")
|
|
serviceID := c.Param("serviceID")
|
|
serviceConfig := &sharedmodel.ServiceConfig{}
|
|
srv.data.Preload("Service").Preload("Subscriptions").Where("connection_id = ? and id = ?", connID, serviceID).Find(&serviceConfig)
|
|
c.JSON(http.StatusOK, serviceConfig)
|
|
}
|
|
|
|
func (srv *UIService) GetPatient(c *gin.Context) {
|
|
connID := c.Param("connID")
|
|
serviceID := c.Param("serviceID")
|
|
patientID := c.Param("patientID")
|
|
patient := &sharedmodel.Subscription{}
|
|
serviceConfig := &sharedmodel.ServiceConfig{}
|
|
if err := srv.data.Preload("FetchProtocol").Preload("FetchProtocol.AuthConfig").Preload("Service").Where("connection_id = ? and id = ?", connID, serviceID).Find(&serviceConfig).Error; err != nil {
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
srv.data.Where("service_config_id = ? and id = ?", serviceID, patientID).Find(&patient)
|
|
|
|
protoconfig := map[string]string{}
|
|
protometa := map[string]string{}
|
|
|
|
err := serviceConfig.FetchProtocol.UnmarshalConfig(&protoconfig)
|
|
|
|
if err != nil {
|
|
c.AbortWithStatus(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
err = patient.GetProtocolMeta(&protometa)
|
|
|
|
if err != nil {
|
|
c.AbortWithStatus(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
Certificates: []tls.Certificate{cert},
|
|
},
|
|
},
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
if resp.StatusCode >= 400 {
|
|
c.AbortWithError(resp.StatusCode, fmt.Errorf("%v", resp.Status))
|
|
return
|
|
}
|
|
|
|
cmd := exec.Command(binFolder+"/ediviewer", binFolder+"/medeur.json", binFolder+"/template.html", "/dev/stdin")
|
|
sin, err := cmd.StdinPipe()
|
|
if err != nil {
|
|
log.Println("[ediviewer] Failed to open stdin pipe:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
defer sin.Close()
|
|
|
|
serr, err := cmd.StderrPipe()
|
|
if err != nil {
|
|
log.Println("[ediviewer] Failed to open stderr pipe:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
defer serr.Close()
|
|
|
|
sout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
log.Println("[ediviewer] Failed to open stdout pipe:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
defer sout.Close()
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
log.Println("[ediviewer] Failed to start:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(3)
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
if _, err := io.Copy(sin, resp.Body); err != nil {
|
|
log.Println("[ediviewer] Error reading EDIFACT:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
if _, err := io.Copy(c.Writer, sout); err != nil {
|
|
log.Println("[ediviewer] Error output EDIFACT:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
defer wg.Done()
|
|
if _, err := io.Copy(os.Stderr, serr); err != nil {
|
|
log.Println("[ediviewer] Error stderr EDIFACT:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
}
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
if err := cmd.Wait(); err != nil {
|
|
log.Println("[ediviewer] Failed:", err)
|
|
c.AbortWithError(http.StatusInternalServerError, err)
|
|
}
|
|
}
|
|
|
|
func (srv *UIService) Authenticate(c *gin.Context) {
|
|
// Maybe authenticate user
|
|
}
|
|
|
|
func (srv *UIService) GetConnections(c *gin.Context) {
|
|
connections := []*sharedmodel.Connection{}
|
|
srv.data.Preload("Services").Preload("Services.Service").Preload("Services.Subscriptions").Find(&connections)
|
|
c.JSON(http.StatusOK, connections)
|
|
}
|
|
|
|
func (srv *UIService) GetRegistrations(c *gin.Context) {
|
|
registrations := []*sharedmodel.Registration{}
|
|
srv.data.Where("status = ?", sharedmodel.RegistrationStatusPending).Find(®istrations)
|
|
c.JSON(http.StatusOK, registrations)
|
|
}
|
|
|
|
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,
|
|
}
|
|
|
|
return srv
|
|
}
|
|
|