diff --git a/backend/pkg/database/sqlite_repository.go b/backend/pkg/database/sqlite_repository.go index 65dacc69f..eafc3ca2a 100644 --- a/backend/pkg/database/sqlite_repository.go +++ b/backend/pkg/database/sqlite_repository.go @@ -252,7 +252,7 @@ func (sr *SqliteRepository) GetSummary(ctx context.Context) (*models.Summary, er //It will also create associations between fhir resources func (sr *SqliteRepository) UpsertRawResource(ctx context.Context, sourceCredential sourceModel.SourceCredential, rawResource sourceModel.RawResourceFhir) (bool, error) { - source := sourceCredential.(models.SourceCredential) + source := sourceCredential.(*models.SourceCredential) //convert from a raw resource (from fasten-sources) to a ResourceFhir (which matches the database models) wrappedResourceModel := &models.ResourceBase{ @@ -289,10 +289,10 @@ func (sr *SqliteRepository) UpsertRawResource(ctx context.Context, sourceCredent } err := sr.AddResourceAssociation( ctx, - &source, + source, wrappedResourceModel.SourceResourceType, wrappedResourceModel.SourceResourceID, - &source, + source, relatedResource.SourceResourceType, relatedResource.SourceResourceID, ) @@ -328,11 +328,16 @@ func (sr *SqliteRepository) UpsertResource(ctx context.Context, wrappedResourceM if err != nil { return false, err } + wrappedFhirResourceModel.SetOriginBase(wrappedResourceModel.OriginBase) + //wrappedFhirResourceModel.SetResourceRaw(wrappedResourceModel.ResourceRaw) + + //TODO: this takes too long, we need to find a way to do this processing faster or in the background async. err = wrappedFhirResourceModel.PopulateAndExtractSearchParameters(json.RawMessage(wrappedResourceModel.ResourceRaw)) if err != nil { return false, fmt.Errorf("An error ocurred while extracting SearchParameters using FHIRPath (%s/%s): %v", wrappedResourceModel.SourceResourceType, wrappedResourceModel.SourceResourceID, err) } + createResult := sr.GormClient.WithContext(ctx).Where(models.OriginBase{ SourceID: wrappedFhirResourceModel.GetSourceID(), SourceResourceID: wrappedFhirResourceModel.GetSourceResourceID(), diff --git a/backend/pkg/database/sqlite_repository_test.go b/backend/pkg/database/sqlite_repository_test.go index 8ccdbc3ba..63f2b1159 100644 --- a/backend/pkg/database/sqlite_repository_test.go +++ b/backend/pkg/database/sqlite_repository_test.go @@ -329,7 +329,7 @@ func (suite *RepositoryTestSuite) TestUpsertRawResource() { authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -386,7 +386,7 @@ func (suite *RepositoryTestSuite) TestUpsertRawResource_WithRelatedResourceAndDu //test wasCreated, err := dbRepo.UpsertRawResource( context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username"), - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -446,7 +446,7 @@ func (suite *RepositoryTestSuite) TestListResources() { testResource1Created, err := dbRepo.UpsertRawResource( context.WithValue(authContext, pkg.ContextKeyTypeAuthUsername, "test_username"), - testSource1Credential, + &testSource1Credential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -461,7 +461,7 @@ func (suite *RepositoryTestSuite) TestListResources() { require.NoError(suite.T(), err) testResource2Created, err := dbRepo.UpsertRawResource( context.WithValue(authContext, pkg.ContextKeyTypeAuthUsername, "test_username"), - testSource2Credential, + &testSource2Credential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "d3fbfb3a-7b8d-45c0-13b4-9666e4d36a3e", @@ -533,7 +533,7 @@ func (suite *RepositoryTestSuite) TestGetResourceByResourceTypeAndId() { authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -586,7 +586,7 @@ func (suite *RepositoryTestSuite) TestGetResourceBySourceId() { authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -639,7 +639,7 @@ func (suite *RepositoryTestSuite) TestGetPatientForSources() { authContext := context.WithValue(context.Background(), pkg.ContextKeyTypeAuthUsername, "test_username") wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "b426b062-8273-4b93-a907-de3176c0567d", @@ -651,7 +651,7 @@ func (suite *RepositoryTestSuite) TestGetPatientForSources() { was2Created, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: "Patient", SourceResourceID: "11111111-8273-4b93-a907-de3176c0567d", @@ -837,7 +837,7 @@ func (suite *RepositoryTestSuite) TestGetSourceSummary() { } wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential, + &testSourceCredential, sourceModels.RawResourceFhir{ SourceResourceType: resourceType, SourceResourceID: *resourceId, @@ -928,7 +928,7 @@ func (suite *RepositoryTestSuite) TestGetSummary() { } wasCreated, err := dbRepo.UpsertRawResource( authContext, - testSourceCredential1, + &testSourceCredential1, sourceModels.RawResourceFhir{ SourceResourceType: resourceType, SourceResourceID: *resourceId, @@ -940,7 +940,7 @@ func (suite *RepositoryTestSuite) TestGetSummary() { wasCreated2, err2 := dbRepo.UpsertRawResource( authContext, - testSourceCredential2, + &testSourceCredential2, sourceModels.RawResourceFhir{ SourceResourceType: resourceType, SourceResourceID: *resourceId + "2", diff --git a/backend/pkg/models/database/interface.go b/backend/pkg/models/database/interface.go index 831a520c5..7a2e8bf6a 100644 --- a/backend/pkg/models/database/interface.go +++ b/backend/pkg/models/database/interface.go @@ -3,11 +3,13 @@ package database import ( "encoding/json" "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models" + "gorm.io/datatypes" ) type IFhirResourceModel interface { models.OriginBaser SetOriginBase(originBase models.OriginBase) + SetResourceRaw(resourceRaw datatypes.JSON) GetSearchParameters() map[string]string PopulateAndExtractSearchParameters(rawResource json.RawMessage) error } diff --git a/backend/pkg/models/resource_base.go b/backend/pkg/models/resource_base.go index bf8eae3a9..fcd0e5bf5 100644 --- a/backend/pkg/models/resource_base.go +++ b/backend/pkg/models/resource_base.go @@ -21,3 +21,7 @@ type ResourceBase struct { func (s *ResourceBase) SetOriginBase(originBase OriginBase) { s.OriginBase = originBase } + +func (s *ResourceBase) SetResourceRaw(resourceRaw datatypes.JSON) { + s.ResourceRaw = resourceRaw +} diff --git a/backend/pkg/models/source_credential.go b/backend/pkg/models/source_credential.go index e675c10d0..660bc3724 100644 --- a/backend/pkg/models/source_credential.go +++ b/backend/pkg/models/source_credential.go @@ -46,47 +46,50 @@ type SourceCredential struct { CodeVerifier string `json:"code_verifier"` } -func (s SourceCredential) GetSourceType() pkg.SourceType { +func (s *SourceCredential) GetSourceType() pkg.SourceType { return s.SourceType } -func (s SourceCredential) GetClientId() string { +func (s *SourceCredential) GetClientId() string { return s.ClientId } -func (s SourceCredential) GetPatientId() string { +func (s *SourceCredential) GetPatientId() string { return s.Patient } -func (s SourceCredential) GetOauthAuthorizationEndpoint() string { +func (s *SourceCredential) GetOauthAuthorizationEndpoint() string { return s.AuthorizationEndpoint } -func (s SourceCredential) GetOauthTokenEndpoint() string { +func (s *SourceCredential) GetOauthTokenEndpoint() string { return s.TokenEndpoint } -func (s SourceCredential) GetApiEndpointBaseUrl() string { +func (s *SourceCredential) GetApiEndpointBaseUrl() string { return s.ApiEndpointBaseUrl } -func (s SourceCredential) GetRefreshToken() string { +func (s *SourceCredential) GetRefreshToken() string { return s.RefreshToken } -func (s SourceCredential) GetAccessToken() string { +func (s *SourceCredential) GetAccessToken() string { return s.AccessToken } -func (s SourceCredential) GetExpiresAt() int64 { +func (s *SourceCredential) GetExpiresAt() int64 { return s.ExpiresAt } -func (s SourceCredential) RefreshTokens(accessToken string, refreshToken string, expiresAt int64) { +func (s *SourceCredential) RefreshTokens(accessToken string, refreshToken string, expiresAt int64) { + if expiresAt > 0 && expiresAt != s.ExpiresAt { + s.ExpiresAt = expiresAt + } + if accessToken != s.AccessToken { // update the "source" credential with new data (which will need to be sent s.AccessToken = accessToken - s.ExpiresAt = expiresAt // Don't overwrite `RefreshToken` with an empty value // if this was a token refreshing request. if refreshToken != "" { diff --git a/backend/pkg/web/handler/source.go b/backend/pkg/web/handler/source.go index 1257994ef..9d514787d 100644 --- a/backend/pkg/web/handler/source.go +++ b/backend/pkg/web/handler/source.go @@ -36,7 +36,7 @@ func CreateSource(c *gin.Context) { } // after creating the source, we should do a bulk import - summary, err := SyncSourceResources(c, logger, databaseRepo, sourceCred) + summary, err := SyncSourceResources(c, logger, databaseRepo, &sourceCred) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false}) return @@ -59,7 +59,7 @@ func SourceSync(c *gin.Context) { } // after creating the source, we should do a bulk import - summary, err := SyncSourceResources(c, logger, databaseRepo, *sourceCred) + summary, err := SyncSourceResources(c, logger, databaseRepo, sourceCred) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false}) return @@ -99,7 +99,7 @@ func CreateManualSource(c *gin.Context) { manualSourceCredential := models.SourceCredential{ SourceType: sourcePkg.SourceTypeManual, } - tempSourceClient, _, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourcePkg.SourceTypeManual, c, logger, manualSourceCredential) + tempSourceClient, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourcePkg.SourceTypeManual, c, logger, &manualSourceCredential) 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}) @@ -122,7 +122,7 @@ func CreateManualSource(c *gin.Context) { return } - manualSourceClient, _, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourcePkg.SourceTypeManual, c, logger, manualSourceCredential) + manualSourceClient, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourcePkg.SourceTypeManual, c, logger, &manualSourceCredential) 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}) @@ -178,22 +178,22 @@ func ListSource(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCreds}) } -func SyncSourceResources(c context.Context, logger *logrus.Entry, databaseRepo database.DatabaseRepository, sourceCred models.SourceCredential) (sourceModels.UpsertSummary, error) { +func SyncSourceResources(c context.Context, logger *logrus.Entry, databaseRepo database.DatabaseRepository, sourceCred *models.SourceCredential) (sourceModels.UpsertSummary, error) { // after creating the source, we should do a bulk import - sourceClient, updatedSource, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourceCred.SourceType, c, logger, sourceCred) + sourceClient, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), sourceCred.SourceType, c, logger, sourceCred) if err != nil { logger.Errorln("An error occurred while initializing hub client using source credential", err) return sourceModels.UpsertSummary{}, err } //TODO: update source - if updatedSource != nil { - logger.Warnf("TODO: source credential has been updated, we should store it in the database: %v", updatedSource) - //err := databaseRepo.CreateSource(c, updatedSource) - //if err != nil { - // logger.Errorln("An error occurred while updating source credential", err) - // return err - //} - } + //if updatedSource != nil { + // logger.Warnf("TODO: source credential has been updated, we should store it in the database: %v", updatedSource) + // //err := databaseRepo.CreateSource(c, updatedSource) + // //if err != nil { + // // logger.Errorln("An error occurred while updating source credential", err) + // // return err + // //} + //} summary, err := sourceClient.SyncAll(databaseRepo) if err != nil { diff --git a/backend/pkg/web/handler/unsafe.go b/backend/pkg/web/handler/unsafe.go index 735805c02..0096fdc5a 100644 --- a/backend/pkg/web/handler/unsafe.go +++ b/backend/pkg/web/handler/unsafe.go @@ -45,22 +45,22 @@ func UnsafeRequestSource(c *gin.Context) { return } - client, updatedSource, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), foundSource.SourceType, c, logger, foundSource) + client, err := factory.GetSourceClient(sourcePkg.GetFastenLighthouseEnv(), foundSource.SourceType, c, logger, foundSource) if err != nil { logger.Errorf("Could not initialize source client %v", err) c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) return } //TODO: if source has been updated, we should save the access/refresh token. - if updatedSource != nil { - logger.Warnf("TODO: source credential has been updated, we should store it in the database: %v", updatedSource) - // err := databaseRepo.CreateSource(c, updatedSource) - // if err != nil { - // logger.Errorf("An error occurred while updating source credential %v", err) - // c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) - // return - // } - } + //if updatedSource != nil { + // logger.Warnf("TODO: source credential has been updated, we should store it in the database: %v", updatedSource) + // // err := databaseRepo.CreateSource(c, updatedSource) + // // if err != nil { + // // logger.Errorf("An error occurred while updating source credential %v", err) + // // c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) + // // return + // // } + //} var resp map[string]interface{} diff --git a/go.mod b/go.mod index 126862ba6..838809bdf 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/dave/jennifer v1.6.1 github.com/dominikbraun/graph v0.15.0 github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 - github.com/fastenhealth/fasten-sources v0.1.15 + github.com/fastenhealth/fasten-sources v0.2.1 github.com/fastenhealth/gofhir-models v0.0.5 github.com/gin-gonic/gin v1.9.0 github.com/glebarez/sqlite v1.5.0 diff --git a/go.sum b/go.sum index 96eaa8ded..a0f781cfc 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,8 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/fastenhealth/fasten-sources v0.1.15 h1:p7jFe29VoEdcc35c3otAqb4dRJ+014KJy89f/pYNMIQ= -github.com/fastenhealth/fasten-sources v0.1.15/go.mod h1:B7pVQcwLuL+rgjSHwlu3p0CySyHN262BkfbYMKVKXTk= +github.com/fastenhealth/fasten-sources v0.2.1 h1:ZdQXg3cRelPo/WsguCU+Ic3F/4GfROeCj/LwIm9NpVM= +github.com/fastenhealth/fasten-sources v0.2.1/go.mod h1:B7pVQcwLuL+rgjSHwlu3p0CySyHN262BkfbYMKVKXTk= github.com/fastenhealth/gofhir-models v0.0.5 h1:wU2Dz+/h9MzZCTRgkQzeq5l0EFuMI6C5xgCbKislFpg= github.com/fastenhealth/gofhir-models v0.0.5/go.mod h1:xB8ikGxu3bUq2b1JYV+CZpHqBaLXpOizFR0eFBCunis= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=