renamed usages of providerId to sourceType

This commit is contained in:
Jason Kulatunga 2022-09-13 21:02:26 -04:00
parent 201b5d5df3
commit 360af5adee
17 changed files with 98 additions and 66 deletions

14
backend/pkg/constants.go Normal file
View File

@ -0,0 +1,14 @@
package pkg
//go:generate stringer -type=SourceType
// SourceType contains all the various medical, insurance, health care providers which Fasten can communicate with
type SourceType string
const (
SourceTypeAetna SourceType = "aetna"
SourceTypeAnthem SourceType = "anthem"
SourceTypeCigna SourceType = "cigna"
SourceTypeHumana SourceType = "humana"
SourceTypeKaiser SourceType = "kaiser"
SourceTypeUnitedHealthcare SourceType = "unitedhealthcare"
)

View File

@ -148,37 +148,37 @@ func (sr *sqliteRepository) ListResources(ctx context.Context, sourceResourceTyp
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ProviderCredentials
// Source
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func (sr *sqliteRepository) CreateSource(ctx context.Context, providerCreds *models.Source) error {
providerCreds.UserID = sr.GetCurrentUser(ctx).ID
func (sr *sqliteRepository) CreateSource(ctx context.Context, sourceCreds *models.Source) error {
sourceCreds.UserID = sr.GetCurrentUser(ctx).ID
if sr.gormClient.WithContext(ctx).Model(&providerCreds).
if sr.gormClient.WithContext(ctx).Model(&sourceCreds).
Where(models.Source{
UserID: providerCreds.UserID,
ProviderId: providerCreds.ProviderId,
PatientId: providerCreds.PatientId}).Updates(&providerCreds).RowsAffected == 0 {
return sr.gormClient.WithContext(ctx).Create(&providerCreds).Error
UserID: sourceCreds.UserID,
SourceType: sourceCreds.SourceType,
PatientId: sourceCreds.PatientId}).Updates(&sourceCreds).RowsAffected == 0 {
return sr.gormClient.WithContext(ctx).Create(&sourceCreds).Error
}
return nil
}
func (sr *sqliteRepository) GetSources(ctx context.Context) ([]models.Source, error) {
var providerCredentials []models.Source
var sourceCreds []models.Source
results := sr.gormClient.WithContext(ctx).
Where(models.Source{UserID: sr.GetCurrentUser(ctx).ID}).
Find(&providerCredentials)
Find(&sourceCreds)
return providerCredentials, results.Error
return sourceCreds, results.Error
}
//func (sr *sqliteRepository) GetSource(ctx context.Context, providerId string) (models.Source, error) {
//
// var providerCredentials models.Source
// results := sr.gormClient.WithContext(ctx).
// Where(models.Source{UserID: sr.GetCurrentUser().ID, ProviderId: providerId}).
// Where(models.Source{UserID: sr.GetCurrentUser().ID, SourceType: providerId}).
// Find(&providerCredentials)
//
// return providerCredential, results.Error

View File

@ -1,8 +1,10 @@
package hub
import (
"context"
"errors"
"fmt"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/config"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/aetna"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/base"
@ -12,21 +14,21 @@ import (
"net/http"
)
func NewClient(providerId string, appConfig config.Interface, globalLogger logrus.FieldLogger, credentials models.Source, testHttpClient ...*http.Client) (base.Client, *models.Source, error) {
func NewClient(sourceType pkg.SourceType, ctx context.Context, appConfig config.Interface, globalLogger logrus.FieldLogger, credentials models.Source, testHttpClient ...*http.Client) (base.Client, *models.Source, error) {
var providerClient base.Client
var sourceClient base.Client
var updatedSource *models.Source
var err error
switch providerId {
case "aetna":
providerClient, updatedSource, err = aetna.NewClient(appConfig, globalLogger, credentials, testHttpClient...)
case "anthem":
providerClient, updatedSource, err = cigna.NewClient(appConfig, globalLogger, credentials, testHttpClient...)
case "cigna":
providerClient, updatedSource, err = cigna.NewClient(appConfig, globalLogger, credentials, testHttpClient...)
switch sourceType {
case pkg.SourceTypeAetna:
sourceClient, updatedSource, err = aetna.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...)
case pkg.SourceTypeAnthem:
sourceClient, updatedSource, err = cigna.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...)
case pkg.SourceTypeCigna:
sourceClient, updatedSource, err = cigna.NewClient(ctx, appConfig, globalLogger, credentials, testHttpClient...)
default:
return nil, updatedSource, errors.New(fmt.Sprintf("Unknown Provider Type: %s", providerId))
return nil, updatedSource, errors.New(fmt.Sprintf("Unknown Source Type: %s", sourceType))
}
return providerClient, updatedSource, err
return sourceClient, updatedSource, err
}

View File

@ -14,8 +14,8 @@ type AetnaClient struct {
*base.FHIR401Client
}
func NewClient(appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (base.Client, *models.Source, error) {
baseClient, updatedSource, err := base.NewFHIR401Client(appConfig, globalLogger, source, testHttpClient...)
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 AetnaClient{
baseClient,
}, updatedSource, err

View File

@ -14,6 +14,7 @@ import (
)
type BaseClient struct {
Context context.Context
AppConfig config.Interface
Logger logrus.FieldLogger
@ -21,14 +22,13 @@ type BaseClient struct {
Source models.Source
}
func NewBaseClient(appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*BaseClient, *models.Source, error) {
func NewBaseClient(ctx context.Context, appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*BaseClient, *models.Source, error) {
var httpClient *http.Client
var updatedSource *models.Source
if len(testHttpClient) == 0 {
//check if we need to refresh the access token
//https://github.com/golang/oauth2/issues/84#issuecomment-520099526
// https://chromium.googlesource.com/external/github.com/golang/oauth2/+/8f816d62a2652f705144857bbbcc26f2c166af9e/oauth2.go#239
ctx := context.Background()
conf := &oauth2.Config{
ClientID: source.ClientId,
ClientSecret: "",
@ -77,6 +77,7 @@ func NewBaseClient(appConfig config.Interface, globalLogger logrus.FieldLogger,
httpClient.Timeout = 10 * time.Second
return &BaseClient{
Context: ctx,
AppConfig: appConfig,
Logger: globalLogger,
OauthClient: httpClient,

View File

@ -1,6 +1,7 @@
package base
import (
"context"
"fmt"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/config"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models"
@ -16,8 +17,8 @@ type FHIR401Client struct {
*BaseClient
}
func NewFHIR401Client(appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*FHIR401Client, *models.Source, error) {
baseClient, updatedSource, err := NewBaseClient(appConfig, globalLogger, source, testHttpClient...)
func NewFHIR401Client(ctx context.Context, appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*FHIR401Client, *models.Source, error) {
baseClient, updatedSource, err := NewBaseClient(ctx, appConfig, globalLogger, source, testHttpClient...)
return &FHIR401Client{
baseClient,
}, updatedSource, err

View File

@ -1,6 +1,7 @@
package base
import (
"context"
"fmt"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/config"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models"
@ -13,8 +14,8 @@ type FHIR430Client struct {
*BaseClient
}
func NewFHIR430Client(appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*FHIR430Client, *models.Source, error) {
baseClient, updatedSource, err := NewBaseClient(appConfig, globalLogger, source, testHttpClient...)
func NewFHIR430Client(ctx context.Context, appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (*FHIR430Client, *models.Source, error) {
baseClient, updatedSource, err := NewBaseClient(ctx, appConfig, globalLogger, source, testHttpClient...)
return &FHIR430Client{
baseClient,
}, updatedSource, err

View File

@ -14,8 +14,8 @@ type CignaClient struct {
*base.FHIR401Client
}
func NewClient(appConfig config.Interface, globalLogger logrus.FieldLogger, source models.Source, testHttpClient ...*http.Client) (base.Client, *models.Source, error) {
baseClient, updatedSource, err := base.NewFHIR401Client(appConfig, globalLogger, source, testHttpClient...)
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 CignaClient{
baseClient,
}, updatedSource, err

View File

@ -1,6 +1,7 @@
package cigna
import (
"context"
mock_config "github.com/fastenhealth/fastenhealth-onprem/backend/pkg/config/mock"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/database"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub/internal/fhir/base"
@ -28,8 +29,8 @@ func TestCignaClient_SyncAll(t *testing.T) {
"type": "test",
})
httpClient := base.OAuthVcrSetup(t, false)
client, err := NewClient(fakeConfig, testLogger, models.Source{
ProviderId: "cigna",
client, _, err := NewClient(context.Background(), fakeConfig, testLogger, models.Source{
SourceType: "cigna",
PatientId: "A00000000000005",
ApiEndpointBaseUrl: "https://p-hi2.digitaledge.cigna.com/PatientAccess/v1-devportal",
ClientId: "e434426c-2aaf-413a-a39a-8f5f6130f287",

View File

@ -7,10 +7,10 @@ import (
)
type ModelBase struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `gorm:"index"`
ID uuid.UUID `json:"id" gorm:"type:uuid;primary_key;"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"`
}
//https://medium.com/@the.hasham.ali/how-to-use-uuid-key-type-with-gorm-cc00d4ec7100

View File

@ -1,14 +1,17 @@
package models
import "github.com/google/uuid"
import (
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg"
"github.com/google/uuid"
)
// Source Data/Medical Provider Credentials
type Source struct {
ModelBase
User User `json:"user,omitempty"`
UserID uuid.UUID `json:"user_id" gorm:"uniqueIndex:idx_user_provider_patient"`
ProviderId string `json:"provider_id" gorm:"uniqueIndex:idx_user_provider_patient"`
PatientId string `json:"patient_id" gorm:"uniqueIndex:idx_user_provider_patient"`
User User `json:"user,omitempty"`
UserID uuid.UUID `json:"user_id" gorm:"uniqueIndex:idx_user_source_patient"`
SourceType pkg.SourceType `json:"source_type" gorm:"uniqueIndex:idx_user_source_patient"`
PatientId string `json:"patient_id" gorm:"uniqueIndex:idx_user_source_patient"`
OauthEndpointBaseUrl string `json:"oauth_endpoint_base_url"`
ApiEndpointBaseUrl string `json:"api_endpoint_base_url"`

View File

@ -1,6 +1,7 @@
package handler
import (
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/database"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/hub"
"github.com/fastenhealth/fastenhealth-onprem/backend/pkg/models"
@ -14,24 +15,24 @@ func CreateSource(c *gin.Context) {
logger := c.MustGet("LOGGER").(*logrus.Entry)
databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository)
providerCred := models.Source{}
if err := c.ShouldBindJSON(&providerCred); err != nil {
logger.Errorln("An error occurred while parsing posted provider credential", err)
sourceCred := models.Source{}
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 Provider Credentials Payload: %v", providerCred)
logger.Infof("Parsed Create Source Credentials Payload: %v", sourceCred)
err := databaseRepo.CreateSource(c, &providerCred)
err := databaseRepo.CreateSource(c, &sourceCred)
if err != nil {
logger.Errorln("An error occurred while storing provider credential", err)
logger.Errorln("An error occurred while storing source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
// after creating the source, we should do a bulk import
sourceClient, updatedSource, err := hub.NewClient(providerCred.ProviderId, nil, logger, providerCred)
sourceClient, updatedSource, err := hub.NewClient(sourceCred.SourceType, c, nil, logger, sourceCred)
if err != nil {
logger.Errorln("An error occurred while initializing hub client using source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
@ -40,7 +41,7 @@ func CreateSource(c *gin.Context) {
if updatedSource != nil {
err := databaseRepo.CreateSource(c, updatedSource)
if err != nil {
logger.Errorln("An error occurred while updating provider credential", err)
logger.Errorln("An error occurred while updating source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
@ -53,20 +54,20 @@ func CreateSource(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": providerCred})
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCred})
}
func ListSource(c *gin.Context) {
logger := c.MustGet("LOGGER").(*logrus.Entry)
databaseRepo := c.MustGet("REPOSITORY").(database.DatabaseRepository)
providerCredentials, err := databaseRepo.GetSources(c)
sourceCreds, err := databaseRepo.GetSources(c)
if err != nil {
logger.Errorln("An error occurred while storing provider credential", err)
logger.Errorln("An error occurred while storing source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": providerCredentials})
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCreds})
}
func RawRequestSource(c *gin.Context) {
@ -75,14 +76,14 @@ func RawRequestSource(c *gin.Context) {
sources, err := databaseRepo.GetSources(c)
if err != nil {
logger.Errorln("An error occurred while storing provider credential", err)
logger.Errorln("An error occurred while storing source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
var foundSource *models.Source
for _, source := range sources {
if source.ProviderId == c.Param("sourceType") {
if source.SourceType == pkg.SourceType(c.Param("sourceType")) {
foundSource = &source
break
}
@ -94,7 +95,7 @@ func RawRequestSource(c *gin.Context) {
return
}
client, updatedSource, err := hub.NewClient(c.Param("sourceType"), nil, logger, *foundSource)
client, updatedSource, err := hub.NewClient(pkg.SourceType(c.Param("sourceType")), c, nil, logger, *foundSource)
if err != nil {
logger.Errorf("Could not initialize source client", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
@ -103,7 +104,7 @@ func RawRequestSource(c *gin.Context) {
if updatedSource != nil {
err := databaseRepo.CreateSource(c, updatedSource)
if err != nil {
logger.Errorln("An error occurred while updating provider credential", err)
logger.Errorln("An error occurred while updating source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}

View File

@ -10,7 +10,7 @@ import {
export class Patient {
//fields
provider_id: string
source_type: string
patient_id: string
age: string

View File

@ -0,0 +1,7 @@
export class ResourceFhir {
user_id?: string
source_id: string
source_resource_type: string
source_resource_id: string
payload: any
}

View File

@ -1,6 +1,6 @@
export class Source {
user_id?: number
provider_id: string
source_type: string
patient_id: string
oauth_endpoint_base_url: string

View File

@ -49,7 +49,7 @@ export class MedicalSourcesComponent implements OnInit {
for (const sourceId in this.sourceLookup) {
let isConnected = false
for(const connectedSource of sourceList){
if(connectedSource.provider_id == sourceId){
if(connectedSource.source_type == sourceId){
this.connectedSourceList.push({"providerId": sourceId, "display": this.sourceLookup[sourceId]["display"]})
isConnected = true
break
@ -128,7 +128,7 @@ export class MedicalSourcesComponent implements OnInit {
//Create FHIR Client
const sourceCredential: Source = {
provider_id: providerId,
source_type: providerId,
oauth_endpoint_base_url: connectData.oauth_endpoint_base_url,
api_endpoint_base_url: connectData.api_endpoint_base_url,
client_id: connectData.client_id,

View File

@ -8,6 +8,7 @@ import {map} from 'rxjs/operators';
import {ResponseWrapper} from '../models/response-wrapper';
import {Source} from '../models/fasten/source';
import {User} from '../models/fasten/user';
import {ResourceFhir} from '../models/fasten/resource_fhir';
@Injectable({
providedIn: 'root'
@ -85,12 +86,12 @@ export class FastenApiService {
);
}
getResources(resourceType: string, resourceId?: string ): Observable<any[]> {
getResources(resourceType: string, resourceId?: string ): Observable<ResourceFhir[]> {
return this._httpClient.get<any>(`${this.getBasePath()}/api/secure/fhir/${resourceType}/${resourceId ? resourceId : ''}`)
.pipe(
map((response: ResponseWrapper) => {
console.log("RESPONSE", response)
return response.data
return response.data as ResourceFhir[]
})
);
}