2022-12-02 20:40:58 -07:00
package handler
import (
"fmt"
2023-08-27 18:09:46 -06:00
"github.com/fastenhealth/fasten-onprem/backend/pkg"
"github.com/fastenhealth/fasten-onprem/backend/pkg/database"
2023-09-09 09:24:25 -06:00
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
2023-08-27 18:09:46 -06:00
"github.com/fastenhealth/fasten-onprem/backend/pkg/models"
2022-12-02 20:40:58 -07:00
"github.com/fastenhealth/fasten-sources/clients/factory"
sourcePkg "github.com/fastenhealth/fasten-sources/pkg"
"github.com/gin-gonic/gin"
2023-10-11 21:43:27 -06:00
"github.com/google/uuid"
2022-12-02 20:40:58 -07:00
"github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
)
2023-10-11 21:43:27 -06:00
func CreateReconnectSource ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2022-12-02 20:40:58 -07:00
sourceCred := models . SourceCredential { }
if err := c . ShouldBindJSON ( & sourceCred ) ; err != nil {
logger . Errorln ( "An error occurred while parsing posted source credential" , err )
c . JSON ( http . StatusBadRequest , gin . H { "success" : false } )
return
}
logger . Infof ( "Parsed Create SourceCredential Credentials Payload: %v" , sourceCred )
2023-07-19 23:45:14 -06:00
if sourceCred . DynamicClientRegistrationMode == "user-authenticated" {
2023-11-04 17:01:00 -06:00
logger . Warnf ( "This client requires a dynamic client registration, starting registration process" )
2023-07-19 23:45:14 -06:00
if len ( sourceCred . RegistrationEndpoint ) == 0 {
2023-11-05 11:53:30 -07:00
err := fmt . Errorf ( "this client requires dynamic registration, but does not provide a registration endpoint: %s" , sourceCred . DynamicClientRegistrationMode )
logger . Errorln ( err )
c . JSON ( http . StatusBadRequest , gin . H { "success" : false , "error" : err . Error ( ) } )
2023-07-19 23:45:14 -06:00
return
}
2023-10-11 21:43:27 -06:00
err := sourceCred . RegisterDynamicClient ( )
2023-07-19 23:45:14 -06:00
if err != nil {
2023-11-05 11:53:30 -07:00
err = fmt . Errorf ( "an error occurred while registering dynamic client: %w" , err )
logger . Errorln ( err )
c . JSON ( http . StatusBadRequest , gin . H { "success" : false , "error" : err . Error ( ) } )
2023-07-19 23:45:14 -06:00
return
}
2023-10-11 21:43:27 -06:00
//generate a JWT token and then use it to get an access token for the dynamic client
err = sourceCred . RefreshDynamicClientAccessToken ( )
2023-07-19 23:45:14 -06:00
if err != nil {
2023-11-05 11:53:30 -07:00
err = fmt . Errorf ( "an error occurred while retrieving access token for dynamic client: %w" , err )
logger . Errorln ( err )
c . JSON ( http . StatusBadRequest , gin . H { "success" : false , "error" : err . Error ( ) } )
2023-07-19 23:45:14 -06:00
return
}
2023-10-11 21:43:27 -06:00
}
2023-07-19 23:45:14 -06:00
2023-10-11 21:43:27 -06:00
if sourceCred . ID != uuid . Nil {
//reconnect
err := databaseRepo . UpdateSource ( c , & sourceCred )
2023-07-19 23:45:14 -06:00
if err != nil {
2023-11-05 11:53:30 -07:00
err = fmt . Errorf ( "an error occurred while reconnecting source credential: %w" , err )
logger . Errorln ( err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : err . Error ( ) } )
2023-07-19 23:45:14 -06:00
return
}
2023-10-11 21:43:27 -06:00
} else {
//create source for the first time
err := databaseRepo . CreateSource ( c , & sourceCred )
2023-07-19 23:45:14 -06:00
if err != nil {
2023-11-05 11:53:30 -07:00
err = fmt . Errorf ( "an error occurred while storing source credential: %w" , err )
logger . Errorln ( err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : err . Error ( ) } )
2023-07-19 23:45:14 -06:00
return
}
}
2023-09-07 22:54:25 -06:00
// after creating the source, we should do a bulk import (in the background)
2023-10-08 17:29:26 -06:00
summary , err := BackgroundJobSyncResources ( GetBackgroundContext ( c ) , logger , databaseRepo , & sourceCred )
2022-12-02 20:40:58 -07:00
if err != nil {
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
c . JSON ( http . StatusOK , gin . H { "success" : true , "source" : sourceCred , "data" : summary } )
}
func SourceSync ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2023-09-20 14:57:12 -06:00
eventBus := c . MustGet ( pkg . ContextKeyTypeEventBusServer ) . ( event_bus . Interface )
2022-12-02 20:40:58 -07:00
logger . Infof ( "Get SourceCredential Credentials: %v" , c . Param ( "sourceId" ) )
sourceCred , err := databaseRepo . GetSource ( c , c . Param ( "sourceId" ) )
if err != nil {
logger . Errorln ( "An error occurred while retrieving source credential" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
2023-09-07 22:54:25 -06:00
// after creating the source, we should do a bulk import (in the background)
2023-10-08 17:29:26 -06:00
summary , err := BackgroundJobSyncResources ( GetBackgroundContext ( c ) , logger , databaseRepo , sourceCred )
2022-12-02 20:40:58 -07:00
if err != nil {
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
2023-09-09 09:24:25 -06:00
//publish event
currentUser , _ := databaseRepo . GetCurrentUser ( c )
2023-09-20 14:57:12 -06:00
err = eventBus . PublishMessage (
2023-09-09 09:24:25 -06:00
models . NewEventSourceComplete (
currentUser . ID . String ( ) ,
sourceCred . ID . String ( ) ,
) ,
)
if err != nil {
logger . Warnf ( "ignoring: an error occurred while publishing sync complete event: %v" , err )
}
2022-12-02 20:40:58 -07:00
c . JSON ( http . StatusOK , gin . H { "success" : true , "source" : sourceCred , "data" : summary } )
}
func CreateManualSource ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2023-09-20 14:57:12 -06:00
eventBus := c . MustGet ( pkg . ContextKeyTypeEventBusServer ) . ( event_bus . Interface )
2022-12-02 20:40:58 -07:00
// single file
file , err := c . FormFile ( "file" )
if err != nil {
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : "could not extract file from form" } )
return
}
fmt . Printf ( "Uploaded filename: %s" , file . Filename )
// create a temporary file to store this uploaded file
bundleFile , err := ioutil . TempFile ( "" , file . Filename )
if err != nil {
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : "could not create temp file" } )
return
}
// Upload the file to specific bundleFile.
err = c . SaveUploadedFile ( file , bundleFile . Name ( ) )
if err != nil {
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : "could not save temp file" } )
return
}
// We cannot save the "SourceCredential" object yet, as we do not know the patientID
// create a "manual" client, which we can use to parse the
manualSourceCredential := models . SourceCredential {
SourceType : sourcePkg . SourceTypeManual ,
}
2023-07-14 20:52:02 -06:00
tempSourceClient , err := factory . GetSourceClient ( sourcePkg . GetFastenLighthouseEnv ( ) , sourcePkg . SourceTypeManual , c , logger , & manualSourceCredential )
2022-12-02 20:40:58 -07:00
if err != nil {
logger . Errorln ( "An error occurred while initializing hub client using manual source without credentials" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
patientId , bundleType , err := tempSourceClient . ExtractPatientId ( bundleFile )
if err != nil {
logger . Errorln ( "An error occurred while extracting patient id" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : err . Error ( ) } )
return
}
manualSourceCredential . Patient = patientId
//store the manualSourceCredential
err = databaseRepo . CreateSource ( c , & manualSourceCredential )
if err != nil {
logger . Errorln ( "An error occurred while creating manual source" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : err . Error ( ) } )
return
}
2023-07-14 20:52:02 -06:00
manualSourceClient , err := factory . GetSourceClient ( sourcePkg . GetFastenLighthouseEnv ( ) , sourcePkg . SourceTypeManual , c , logger , & manualSourceCredential )
2022-12-02 20:40:58 -07:00
if err != nil {
logger . Errorln ( "An error occurred while initializing hub client using manual source with credential" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
summary , err := manualSourceClient . SyncAllBundle ( databaseRepo , bundleFile , bundleType )
if err != nil {
logger . Errorln ( "An error occurred while processing bundle" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false , "error" : err . Error ( ) } )
return
}
2023-09-09 09:24:25 -06:00
//publish event
currentUser , _ := databaseRepo . GetCurrentUser ( c )
2023-09-20 14:57:12 -06:00
err = eventBus . PublishMessage (
2023-09-09 09:24:25 -06:00
models . NewEventSourceComplete (
currentUser . ID . String ( ) ,
manualSourceCredential . ID . String ( ) ,
) ,
)
if err != nil {
logger . Warnf ( "ignoring: an error occurred while publishing sync complete event: %v" , err )
}
2023-01-10 20:23:47 -07:00
c . JSON ( http . StatusOK , gin . H { "success" : true , "data" : summary , "source" : manualSourceCredential } )
2023-09-09 09:24:25 -06:00
2022-12-02 20:40:58 -07:00
}
func GetSource ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2022-12-02 20:40:58 -07:00
sourceCred , err := databaseRepo . GetSource ( c , c . Param ( "sourceId" ) )
if err != nil {
logger . Errorln ( "An error occurred while retrieving source credential" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
c . JSON ( http . StatusOK , gin . H { "success" : true , "data" : sourceCred } )
}
func GetSourceSummary ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2022-12-02 20:40:58 -07:00
sourceSummary , err := databaseRepo . GetSourceSummary ( c , c . Param ( "sourceId" ) )
if err != nil {
logger . Errorln ( "An error occurred while retrieving source summary" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
c . JSON ( http . StatusOK , gin . H { "success" : true , "data" : sourceSummary } )
}
func ListSource ( c * gin . Context ) {
2023-01-10 20:23:47 -07:00
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
2022-12-02 20:40:58 -07:00
sourceCreds , err := databaseRepo . GetSources ( c )
if err != nil {
logger . Errorln ( "An error occurred while listing source credentials" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
c . JSON ( http . StatusOK , gin . H { "success" : true , "data" : sourceCreds } )
}
2023-10-11 08:54:18 -06:00
func DeleteSource ( c * gin . Context ) {
logger := c . MustGet ( pkg . ContextKeyTypeLogger ) . ( * logrus . Entry )
databaseRepo := c . MustGet ( pkg . ContextKeyTypeDatabase ) . ( database . DatabaseRepository )
rowsEffected , err := databaseRepo . DeleteSource ( c , c . Param ( "sourceId" ) )
if err != nil {
logger . Errorln ( "An error occurred while deleting source credential" , err )
c . JSON ( http . StatusInternalServerError , gin . H { "success" : false } )
return
}
c . JSON ( http . StatusOK , gin . H { "success" : true , "data" : rowsEffected } )
}