From cc485a061565f2536b9571696d781c353313942f Mon Sep 17 00:00:00 2001 From: Jason Kulatunga Date: Sun, 18 Sep 2022 00:36:53 -0700 Subject: [PATCH] support logica service. update dashboard. moved RAW API endpoint outside of the secure block. --- backend/pkg/constants.go | 1 + backend/pkg/database/interface.go | 1 + backend/pkg/database/sqlite_repository.go | 30 +++++++++++++ backend/pkg/hub/factory.go | 3 ++ .../pkg/hub/internal/fhir/logica/client.go | 42 ++++++++++++++++++ backend/pkg/models/summary.go | 1 + backend/pkg/web/handler/source.go | 30 ++++++------- backend/pkg/web/server.go | 11 +++-- frontend/src/app/models/fasten/summary.ts | 2 + .../pages/dashboard/dashboard.component.html | 5 +-- .../pages/dashboard/dashboard.component.ts | 14 +++++- .../medical-sources.component.ts | 14 +++++- frontend/src/assets/sources/manual.png | Bin 0 -> 24297 bytes 13 files changed, 127 insertions(+), 27 deletions(-) create mode 100644 backend/pkg/hub/internal/fhir/logica/client.go create mode 100644 frontend/src/assets/sources/manual.png diff --git a/backend/pkg/constants.go b/backend/pkg/constants.go index ac84157a..9ce2c7c9 100644 --- a/backend/pkg/constants.go +++ b/backend/pkg/constants.go @@ -13,4 +13,5 @@ const ( SourceTypeHumana SourceType = "humana" SourceTypeKaiser SourceType = "kaiser" SourceTypeUnitedHealthcare SourceType = "unitedhealthcare" + SourceTypeLogica SourceType = "logica" ) diff --git a/backend/pkg/database/interface.go b/backend/pkg/database/interface.go index e83e91ae..5e73a03d 100644 --- a/backend/pkg/database/interface.go +++ b/backend/pkg/database/interface.go @@ -19,6 +19,7 @@ type DatabaseRepository interface { GetResource(context.Context, string) (*models.ResourceFhir, error) GetResourceBySourceId(context.Context, string, string) (*models.ResourceFhir, error) ListResources(context.Context, models.ListResourceQueryOptions) ([]models.ResourceFhir, error) + GetPatientForSources(ctx context.Context) ([]models.ResourceFhir, error) //UpsertProfile(context.Context, *models.Profile) error //UpsertOrganziation(context.Context, *models.Organization) error diff --git a/backend/pkg/database/sqlite_repository.go b/backend/pkg/database/sqlite_repository.go index ca3ce97b..0eb83519 100644 --- a/backend/pkg/database/sqlite_repository.go +++ b/backend/pkg/database/sqlite_repository.go @@ -138,9 +138,16 @@ func (sr *sqliteRepository) GetSummary(ctx context.Context) (*models.Summary, er return nil, err } + // we want the main Patient for each source + patients, err := sr.GetPatientForSources(ctx) + if err != nil { + return nil, err + } + summary := &models.Summary{ Sources: sources, ResourceTypeCounts: resourceCountResults, + Patients: patients, } return summary, nil @@ -237,6 +244,29 @@ func (sr *sqliteRepository) GetResource(ctx context.Context, resourceId string) return &wrappedResourceModel, results.Error } +// Get the patient for each source (for the current user) +func (sr *sqliteRepository) GetPatientForSources(ctx context.Context) ([]models.ResourceFhir, error) { + + //SELECT * FROM resource_fhirs WHERE user_id = "" and source_resource_type = "Patient" GROUP BY source_id + + //var sourceCred models.Source + //results := sr.gormClient.WithContext(ctx). + // Where(models.Source{UserID: sr.GetCurrentUser(ctx).ID, ModelBase: models.ModelBase{ID: sourceUUID}}). + // First(&sourceCred) + + var wrappedResourceModels []models.ResourceFhir + results := sr.gormClient.WithContext(ctx). + Model(models.ResourceFhir{}). + Group("source_id"). + Where(models.OriginBase{ + UserID: sr.GetCurrentUser(ctx).ID, + SourceResourceType: "Patient", + }). + Find(&wrappedResourceModels) + + return wrappedResourceModels, results.Error +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Source //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/backend/pkg/hub/factory.go b/backend/pkg/hub/factory.go index 5ae2d0db..2e737165 100644 --- a/backend/pkg/hub/factory.go +++ b/backend/pkg/hub/factory.go @@ -9,6 +9,7 @@ import ( "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/aetna" "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/base" "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/cigna" + "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/logica" "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/manual" "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models" "github.com/sirupsen/logrus" @@ -27,6 +28,8 @@ func NewClient(sourceType pkg.SourceType, ctx context.Context, appConfig config. sourceClient, updatedSource, err = cigna.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...) case pkg.SourceTypeCigna: sourceClient, updatedSource, err = cigna.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...) + case pkg.SourceTypeLogica: + sourceClient, updatedSource, err = logica.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...) case pkg.SourceTypeManual: sourceClient, updatedSource, err = manual.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...) default: diff --git a/backend/pkg/hub/internal/fhir/logica/client.go b/backend/pkg/hub/internal/fhir/logica/client.go new file mode 100644 index 00000000..3564749a --- /dev/null +++ b/backend/pkg/hub/internal/fhir/logica/client.go @@ -0,0 +1,42 @@ +package logica + +import ( + "context" + "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/config" + "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/database" + "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/base" + "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models" + "github.com/sirupsen/logrus" + "net/http" +) + +type LogicaClient struct { + *base.FHIR401Client +} + +func NewClient(ctx context.Context, appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (base.Client, *models.Source, error) { + baseClient, updatedSource, err := base.NewFHIR401Client(ctx, appConfig, globalLogger, source, testHttpClient...) + return LogicaClient{ + baseClient, + }, updatedSource, err +} + +func (c LogicaClient) SyncAll(db database.DatabaseRepository) error { + + bundle, err := c.GetPatientBundle(c.Source.PatientId) + if err != nil { + return err + } + + wrappedResourceModels, err := c.ProcessBundle(bundle) + + //todo, create the resources in dependency order + + for _, apiModel := range wrappedResourceModels { + err = db.UpsertResource(context.Background(), apiModel) + if err != nil { + return err + } + } + return nil +} diff --git a/backend/pkg/models/summary.go b/backend/pkg/models/summary.go index 0a23b739..be21b1f2 100644 --- a/backend/pkg/models/summary.go +++ b/backend/pkg/models/summary.go @@ -2,5 +2,6 @@ package models type Summary struct { Sources []Source `json:"sources,omitempty"` + Patients []ResourceFhir `json:"patients,omitempty"` ResourceTypeCounts []map[string]interface{} `json:"resource_type_counts,omitempty"` } diff --git a/backend/pkg/web/handler/source.go b/backend/pkg/web/handler/source.go index 35e00b35..0ccfb0ba 100644 --- a/backend/pkg/web/handler/source.go +++ b/backend/pkg/web/handler/source.go @@ -148,38 +148,34 @@ func RawRequestSource(c *gin.Context) { logger := c.MustGet("LOGGER").(*logrus.Entry) databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository) - sources, err := databaseRepo.GetSources(c) - if err != nil { - logger.Errorln("An error occurred while storing source credential", err) - c.JSON(http.StatusInternalServerError, gin.H{"success": false}) - return - } + //!!!!!!INSECURE!!!!!!S + //We're setting the username to a user provided value, this is insecure, but required for calling databaseRepo fns + c.Set("AUTH_USERNAME", c.Param("username")) - var foundSource *models.Source - for _, source := range sources { - if source.SourceType == pkg.SourceType(c.Param("sourceType")) { - foundSource = &source - break - } + foundSource, err := databaseRepo.GetSource(c, c.Param("sourceId")) + if err != nil { + logger.Errorln("An error occurred while finding source credential", err) + c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) + return } if foundSource == nil { logger.Errorf("Did not source credentials for %s", c.Param("sourceType")) - c.JSON(http.StatusNotFound, gin.H{"success": false}) + c.JSON(http.StatusNotFound, gin.H{"success": false, "error": err.Error()}) return } - client, updatedSource, err := hub.NewClient(pkg.SourceType(c.Param("sourceType")), c, nil, logger, *foundSource) + client, updatedSource, err := hub.NewClient(foundSource.SourceType, c, nil, logger, *foundSource) if err != nil { logger.Errorf("Could not initialize source client", err) - c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) return } if updatedSource != nil { err := databaseRepo.CreateSource(c, updatedSource) if err != nil { logger.Errorln("An error occurred while updating source credential", err) - c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) return } } @@ -188,7 +184,7 @@ func RawRequestSource(c *gin.Context) { err = client.GetRequest(strings.TrimSuffix(c.Param("path"), "/"), &resp) if err != nil { logger.Errorf("Error making raw request", err) - c.JSON(http.StatusInternalServerError, gin.H{"success": false}) + c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"success": true, "data": resp}) diff --git a/backend/pkg/web/server.go b/backend/pkg/web/server.go index cfa798c7..88d5685c 100644 --- a/backend/pkg/web/server.go +++ b/backend/pkg/web/server.go @@ -52,12 +52,17 @@ func (ae *AppEngine) Setup(logger *logrus.Entry) *gin.Engine { secure.GET("/source", handler.ListSource) secure.GET("/source/:sourceId", handler.GetSource) secure.GET("/source/:sourceId/summary", handler.GetSourceSummary) - //in debug mode, this endpoint lets us request data directly from the source api - secure.GET("/source/raw/:sourceType/*path", handler.RawRequestSource) - secure.GET("/resource/fhir", handler.ListResourceFhir) // secure.GET("/resource/fhir/:resourceId", handler.GetResourceFhir) } + + if ae.Config.GetString("log.level") == "DEBUG" { + //in debug mode, this endpoint lets us request data directly from the source api + ae.Logger.Warningf("***INSECURE*** ***INSECURE*** DEBUG mode enables developer functionality, including unauthenticated raw api requests") + + //http://localhost:9090/api/raw/test@test.com/436d7277-ad56-41ce-9823-44e353d1b3f6/Patient/smart-1288992 + api.GET("/raw/:username/:sourceId/*path", handler.RawRequestSource) + } } } diff --git a/frontend/src/app/models/fasten/summary.ts b/frontend/src/app/models/fasten/summary.ts index 5384e91f..989fba14 100644 --- a/frontend/src/app/models/fasten/summary.ts +++ b/frontend/src/app/models/fasten/summary.ts @@ -1,7 +1,9 @@ import {Source} from './source'; import {ResourceTypeCounts} from './source-summary'; +import {ResourceFhir} from './resource_fhir'; export class Summary { sources: Source[] + patients: ResourceFhir[] resource_type_counts: ResourceTypeCounts[] } diff --git a/frontend/src/app/pages/dashboard/dashboard.component.html b/frontend/src/app/pages/dashboard/dashboard.component.html index 64f0f04a..ab707867 100644 --- a/frontend/src/app/pages/dashboard/dashboard.component.html +++ b/frontend/src/app/pages/dashboard/dashboard.component.html @@ -94,7 +94,7 @@
- +

19

@@ -154,8 +154,7 @@
{{source.source_type}}

- GeeksforGeeks is a computer science portal. - It is a best programming platform. + {{getPatientSummary(patientForSource[source.id]?.payload)}}

diff --git a/frontend/src/app/pages/dashboard/dashboard.component.ts b/frontend/src/app/pages/dashboard/dashboard.component.ts index b15acf42..d617ee89 100644 --- a/frontend/src/app/pages/dashboard/dashboard.component.ts +++ b/frontend/src/app/pages/dashboard/dashboard.component.ts @@ -5,6 +5,7 @@ import {Source} from '../../models/fasten/source'; import {Router} from '@angular/router'; import {Summary} from '../../models/fasten/summary'; import {ResourceTypeCounts} from '../../models/fasten/source-summary'; +import {ResourceFhir} from '../../models/fasten/resource_fhir'; @Component({ selector: 'app-dashboard', @@ -16,6 +17,7 @@ export class DashboardComponent implements OnInit { sources: Source[] = [] encounterCount: number = 0 recordsCount: number = 0 + patientForSource: {[name: string]: ResourceFhir} = {} constructor(private fastenApi: FastenApiService, private router: Router) { } @@ -33,9 +35,11 @@ export class DashboardComponent implements OnInit { this.encounterCount = resourceTypeInfo.count } }) - }) - // this.fastenApi.getResources('Patient') + summary.patients.forEach((resourceFhir) => { + this.patientForSource[resourceFhir.source_id] = resourceFhir + }) + }) } selectSource(selectedSource: Source){ @@ -44,6 +48,12 @@ export class DashboardComponent implements OnInit { }); } + getPatientSummary(patient: any) { + if(patient && patient.name && patient.name[0]){ + return `${patient.name[0].family}, ${patient.name[0].given.join(' ')}` + } + return '' + } pageViewChartData = [{ label: 'This week', diff --git a/frontend/src/app/pages/medical-sources/medical-sources.component.ts b/frontend/src/app/pages/medical-sources/medical-sources.component.ts index 9e6b8dfb..0122f8a2 100644 --- a/frontend/src/app/pages/medical-sources/medical-sources.component.ts +++ b/frontend/src/app/pages/medical-sources/medical-sources.component.ts @@ -5,7 +5,7 @@ import {LighthouseSource} from '../../models/lighthouse/lighthouse-source'; import * as Oauth from '@panva/oauth4webapi'; import {AuthorizeClaim} from '../../models/lighthouse/authorize-claim'; import {Source} from '../../models/fasten/source'; -import {getAccessTokenExpiration} from 'fhirclient/lib/lib'; +import {getAccessTokenExpiration, jwtDecode} from 'fhirclient/lib/lib'; import BrowserAdapter from 'fhirclient/lib/adapters/BrowserAdapter'; import {Observable, of, throwError} from 'rxjs'; import {concatMap, delay, retryWhen} from 'rxjs/operators'; @@ -34,6 +34,7 @@ export class MedicalSourcesComponent implements OnInit { "humana": {"display": "Humana"}, "kaiser": {"display": "Kaiser"}, "unitedhealthcare": {"display": "United Healthcare"}, + "logica": {"display": "Logica Sandbox"}, } connectedSourceList = [] @@ -103,7 +104,7 @@ export class MedicalSourcesComponent implements OnInit { issuer: `${authorizationUrl.protocol}//${authorizationUrl.host}`, authorization_endpoint: `${connectData.oauth_endpoint_base_url}/authorize`, token_endpoint: `${connectData.oauth_endpoint_base_url}/token`, - introspect_endpoint: `${connectData.oauth_endpoint_base_url}/introspect`, + introspection_endpoint: `${connectData.oauth_endpoint_base_url}/introspect`, } console.log("STARTING--- Oauth.validateAuthResponse") @@ -125,6 +126,15 @@ export class MedicalSourcesComponent implements OnInit { console.log("ENDING--- Oauth.authorizationCodeGrantRequest", payload) + //If payload.patient is not set, make sure we extract the patient ID from the id_token or make an introspection req + if(!payload.patient){ + // + console.log("NO PATIENT ID present, decoding jwt to extract patient") + //const introspectionResp = await Oauth.introspectionRequest(as, client, payload.access_token) + //console.log(introspectionResp) + payload.patient = jwtDecode(payload.id_token, new BrowserAdapter())["profile"].replace(/^(Patient\/)/,'') + } + //Create FHIR Client const sourceCredential: Source = { source_type: sourceType, diff --git a/frontend/src/assets/sources/manual.png b/frontend/src/assets/sources/manual.png new file mode 100644 index 0000000000000000000000000000000000000000..050908c513b2b5c4396d3bf6527be5b680d94088 GIT binary patch literal 24297 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 Bi9rAW literal 0 HcmV?d00001