package main
import (
"context"
"crypto/tls"
"fmt"
"io"
"log"
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"whiteboxsystems.nl/okapidemo/dvzaservice/model"
"whiteboxsystems.nl/okapidemo/sharedmodel"
)
type UIService struct {
srv * http . Server
inited bool
data * gorm . DB
clientCert tls . Certificate
}
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 ( ) {
if ! srv . inited {
srv . init ( )
}
log . Printf ( "Listening on %v\n" , srv . srv . Addr )
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 )
// r.GET("/api/systems/:sysid/patients", srv.GetPatients)
// r.GET("/api/systems/:sysid/patients/:patid", srv.GetPatient)
srv . inited = true
}
func ( srv * UIService ) GetIndex ( c * gin . Context ) {
c . HTML ( http . StatusOK , "index.html" , gin . H { } )
}
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 { }
srv . data . Preload ( "FetchProtocol" ) . Preload ( "FetchProtocol.AuthConfig" ) . Preload ( "Service" ) . Where ( "connection_id = ? and id = ?" , connID , serviceID ) . Find ( & serviceConfig )
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?id=%v" , protoconfig [ "url" ] , protometa [ "patientID" ] )
req , _ := http . NewRequest ( "GET" , url , nil )
req . Header . Set ( "Authorization" , serviceConfig . FetchProtocol . AuthConfig . Raw )
client := & http . Client {
Transport : & http . Transport {
TLSClientConfig : & tls . Config {
InsecureSkipVerify : true ,
} ,
} ,
}
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
}
io . Copy ( c . Writer , resp . Body )
}
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 ( & registrations )
c . JSON ( http . StatusOK , registrations )
}
func NewUIServer ( addr string ) * UIService {
cert := loadCert ( )
srv := & UIService { srv : & http . Server {
Addr : addr ,
Handler : gin . Default ( ) ,
} , clientCert : * cert }
return srv
}