Merge pull request #275 from fastenhealth/nickmurray/add-postgres-db-option

This commit is contained in:
Jason Kulatunga 2023-10-16 11:43:36 -07:00 committed by GitHub
commit 8861e4b6ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1469 additions and 1245 deletions

View File

@ -30,6 +30,7 @@ func (c *configuration) Init() error {
c.SetDefault("web.allow_unsafe_endpoints", false) c.SetDefault("web.allow_unsafe_endpoints", false)
c.SetDefault("web.src.frontend.path", "/opt/fasten/web") c.SetDefault("web.src.frontend.path", "/opt/fasten/web")
c.SetDefault("database.type", "sqlite")
c.SetDefault("database.location", "/opt/fasten/db/fasten.db") c.SetDefault("database.location", "/opt/fasten/db/fasten.db")
c.SetDefault("cache.location", "/opt/fasten/cache/") c.SetDefault("cache.location", "/opt/fasten/cache/")

View File

@ -5,6 +5,8 @@ type BackgroundJobStatus string
type BackgroundJobType string type BackgroundJobType string
type BackgroundJobSchedule string type BackgroundJobSchedule string
type DatabaseRepositoryType string
const ( const (
ResourceListPageSize int = 20 ResourceListPageSize int = 20
@ -36,4 +38,7 @@ const (
BackgroundJobScheduleWeekly BackgroundJobSchedule = "WEEKLY" BackgroundJobScheduleWeekly BackgroundJobSchedule = "WEEKLY"
BackgroundJobScheduleBiWeekly BackgroundJobSchedule = "BIWEEKLY" BackgroundJobScheduleBiWeekly BackgroundJobSchedule = "BIWEEKLY"
BackgroundJobScheduleMonthly BackgroundJobSchedule = "MONTHLY" BackgroundJobScheduleMonthly BackgroundJobSchedule = "MONTHLY"
DatabaseRepositoryTypeSqlite DatabaseRepositoryType = "sqlite"
DatabaseRepositoryTypePostgres DatabaseRepositoryType = "postgres"
) )

View File

@ -0,0 +1,20 @@
package database
import (
"github.com/fastenhealth/fasten-onprem/backend/pkg"
"github.com/fastenhealth/fasten-onprem/backend/pkg/config"
"github.com/fastenhealth/fasten-onprem/backend/pkg/errors"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
"github.com/sirupsen/logrus"
)
func NewRepository(appConfig config.Interface, globalLogger logrus.FieldLogger, eventBus event_bus.Interface) (DatabaseRepository, error) {
switch pkg.DatabaseRepositoryType(appConfig.GetString("database.type")) {
case pkg.DatabaseRepositoryTypeSqlite:
return newSqliteRepository(appConfig, globalLogger, eventBus)
case pkg.DatabaseRepositoryTypePostgres:
return newPostgresRepository(appConfig, globalLogger, eventBus)
default:
return nil, errors.DatabaseTypeNotSupportedError(appConfig.GetString("database.type"))
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,15 @@ package database
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"strings"
"github.com/dominikbraun/graph" "github.com/dominikbraun/graph"
"github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models" "github.com/fastenhealth/fasten-onprem/backend/pkg/models"
"github.com/fastenhealth/fasten-onprem/backend/pkg/utils"
databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database"
"github.com/fastenhealth/fasten-onprem/backend/pkg/utils"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"log"
"strings"
) )
type VertexResourcePlaceholder struct { type VertexResourcePlaceholder struct {
@ -28,8 +29,8 @@ func (rp *VertexResourcePlaceholder) ID() string {
// Retrieve a list of all fhir resources (vertex), and a list of all associations (edge) // Retrieve a list of all fhir resources (vertex), and a list of all associations (edge)
// Generate a graph // Generate a graph
// return list of root nodes, and their flattened related resources. // return list of root nodes, and their flattened related resources.
func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graphType pkg.ResourceGraphType, options models.ResourceGraphOptions) (map[string][]*models.ResourceBase, *models.ResourceGraphMetadata, error) { func (gr *GormRepository) GetFlattenedResourceGraph(ctx context.Context, graphType pkg.ResourceGraphType, options models.ResourceGraphOptions) (map[string][]*models.ResourceBase, *models.ResourceGraphMetadata, error) {
currentUser, currentUserErr := sr.GetCurrentUser(ctx) currentUser, currentUserErr := gr.GetCurrentUser(ctx)
if currentUserErr != nil { if currentUserErr != nil {
return nil, nil, currentUserErr return nil, nil, currentUserErr
} }
@ -45,7 +46,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
var relatedResourceRelationships []models.RelatedResource var relatedResourceRelationships []models.RelatedResource
// SELECT * FROM related_resources WHERE user_id = "53c1e930-63af-46c9-b760-8e83cbc1abd9"; // SELECT * FROM related_resources WHERE user_id = "53c1e930-63af-46c9-b760-8e83cbc1abd9";
result := sr.GormClient.WithContext(ctx). result := gr.GormClient.WithContext(ctx).
Where(models.RelatedResource{ Where(models.RelatedResource{
ResourceBaseUserID: currentUser.ID, ResourceBaseUserID: currentUser.ID,
}). }).
@ -59,7 +60,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
g := graph.New(resourceVertexId, graph.Directed(), graph.Acyclic(), graph.Rooted()) g := graph.New(resourceVertexId, graph.Directed(), graph.Acyclic(), graph.Rooted())
//// Get list of all resources TODO - REPLACED THIS //// Get list of all resources TODO - REPLACED THIS
//wrappedResourceModels, err := sr.ListResources(ctx, models.ListResourceQueryOptions{}) //wrappedResourceModels, err := gr.ListResources(ctx, models.ListResourceQueryOptions{})
//if err != nil { //if err != nil {
// return nil, err // return nil, err
//} //}
@ -109,7 +110,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
} }
//add recriprocial relationships (depending on the graph type) //add recriprocial relationships (depending on the graph type)
relatedResourceRelationships = sr.PopulateGraphTypeReciprocalRelationships(graphType, relatedResourceRelationships) relatedResourceRelationships = gr.PopulateGraphTypeReciprocalRelationships(graphType, relatedResourceRelationships)
//add edges to graph //add edges to graph
for _, relationship := range relatedResourceRelationships { for _, relationship := range relatedResourceRelationships {
@ -121,7 +122,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
if err != nil { if err != nil {
//this may occur because vertices may not exist //this may occur because vertices may not exist
sr.Logger.Warnf("ignoring, an error occurred while adding edge: %v", err) gr.Logger.Warnf("ignoring, an error occurred while adding edge: %v", err)
} }
} }
@ -200,7 +201,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
// Step 2: now that we've created a relationship graph using placeholders, we need to determine which page of resources to return // Step 2: now that we've created a relationship graph using placeholders, we need to determine which page of resources to return
// and look up the actual resources from the database. // and look up the actual resources from the database.
resourceListDictionary, totalElements, err := sr.InflateResourceGraphAtPage(resourcePlaceholderListDictionary, options.Page) resourceListDictionary, totalElements, err := gr.InflateResourceGraphAtPage(resourcePlaceholderListDictionary, options.Page)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("error while paginating & inflating resource graph: %v", err) return nil, nil, fmt.Errorf("error while paginating & inflating resource graph: %v", err)
} }
@ -215,7 +216,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
SourceID: resource.SourceID.String(), SourceID: resource.SourceID.String(),
UserID: resource.UserID.String(), UserID: resource.UserID.String(),
}) })
sr.Logger.Debugf("populating resourcePlaceholder: %s", vertexId) gr.Logger.Debugf("populating resourcePlaceholder: %s", vertexId)
resource.RelatedResource = []*models.ResourceBase{} resource.RelatedResource = []*models.ResourceBase{}
@ -226,9 +227,9 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
//skip the current resourcePlaceholder if it's referenced in this list. //skip the current resourcePlaceholder if it's referenced in this list.
//also skip the current resourcePlaceholder if its a Binary resourcePlaceholder (which is a special case) //also skip the current resourcePlaceholder if its a Binary resourcePlaceholder (which is a special case)
if vertexId != resourceVertexId(relatedResourcePlaceholder) && relatedResourcePlaceholder.ResourceType != "Binary" { if vertexId != resourceVertexId(relatedResourcePlaceholder) && relatedResourcePlaceholder.ResourceType != "Binary" {
relatedResource, err := sr.GetResourceByResourceTypeAndId(ctx, relatedResourcePlaceholder.ResourceType, relatedResourcePlaceholder.ResourceID) relatedResource, err := gr.GetResourceByResourceTypeAndId(ctx, relatedResourcePlaceholder.ResourceType, relatedResourcePlaceholder.ResourceID)
if err != nil { if err != nil {
sr.Logger.Warnf("ignoring, cannot safely handle error which occurred while getting related resource: %v", err) gr.Logger.Warnf("ignoring, cannot safely handle error which occurred while getting related resource: %v", err)
return true return true
} }
resource.RelatedResource = append( resource.RelatedResource = append(
@ -268,9 +269,9 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
vertexId := resourceKeysVertexId(currentResource.SourceID.String(), currentResource.SourceResourceType, currentResource.SourceResourceID) vertexId := resourceKeysVertexId(currentResource.SourceID.String(), currentResource.SourceResourceType, currentResource.SourceResourceID)
for relatedVertexId, _ := range adjacencyMap[vertexId] { for relatedVertexId, _ := range adjacencyMap[vertexId] {
relatedResourcePlaceholder, _ := g.Vertex(relatedVertexId) relatedResourcePlaceholder, _ := g.Vertex(relatedVertexId)
relatedResourceFhir, err := sr.GetResourceByResourceTypeAndId(ctx, relatedResourcePlaceholder.ResourceType, relatedResourcePlaceholder.ResourceID) relatedResourceFhir, err := gr.GetResourceByResourceTypeAndId(ctx, relatedResourcePlaceholder.ResourceType, relatedResourcePlaceholder.ResourceID)
if err != nil { if err != nil {
sr.Logger.Warnf("ignoring, cannot safely handle error which occurred while getting related resource (flatten=false): %v", err) gr.Logger.Warnf("ignoring, cannot safely handle error which occurred while getting related resource (flatten=false): %v", err)
continue continue
} }
flattenRelatedResourcesFn(relatedResourceFhir) flattenRelatedResourcesFn(relatedResourceFhir)
@ -295,7 +296,7 @@ func (sr *SqliteRepository) GetFlattenedResourceGraph(ctx context.Context, graph
// - sort the root resources by date, desc // - sort the root resources by date, desc
// - use the page number + page size to determine which root resources to return // - use the page number + page size to determine which root resources to return
// - return a dictionary of "source" resource lists // - return a dictionary of "source" resource lists
func (sr *SqliteRepository) InflateResourceGraphAtPage(resourcePlaceholderListDictionary map[string][]*VertexResourcePlaceholder, page int) (map[string][]*models.ResourceBase, int, error) { func (gr *GormRepository) InflateResourceGraphAtPage(resourcePlaceholderListDictionary map[string][]*VertexResourcePlaceholder, page int) (map[string][]*models.ResourceBase, int, error) {
totalElements := 0 totalElements := 0
// Step 3a: since we cant calulate the sort order until the resources are loaded, we need to load all the root resources first. // Step 3a: since we cant calulate the sort order until the resources are loaded, we need to load all the root resources first.
@ -319,7 +320,7 @@ func (sr *SqliteRepository) InflateResourceGraphAtPage(resourcePlaceholderListDi
return nil, totalElements, err return nil, totalElements, err
} }
var tableWrappedResourceModels []models.ResourceBase var tableWrappedResourceModels []models.ResourceBase
sr.GormClient. gr.GormClient.
Where("(user_id, source_id, source_resource_type, source_resource_id) IN ?", selectList). Where("(user_id, source_id, source_resource_type, source_resource_id) IN ?", selectList).
Table(tableName). Table(tableName).
Find(&tableWrappedResourceModels) Find(&tableWrappedResourceModels)
@ -359,7 +360,7 @@ func (sr *SqliteRepository) InflateResourceGraphAtPage(resourcePlaceholderListDi
// edges are always "strongly connected", however "source" nodes (roots, like Condition or Encounter -- depending on ) are only one way. // edges are always "strongly connected", however "source" nodes (roots, like Condition or Encounter -- depending on ) are only one way.
// add an edge from every resource to its related resource. Keep in mind that FHIR resources may not contain reciprocal edges, so we ensure the graph is rooted by flipping any // add an edge from every resource to its related resource. Keep in mind that FHIR resources may not contain reciprocal edges, so we ensure the graph is rooted by flipping any
// related resources that are "Condition" or "Encounter" // related resources that are "Condition" or "Encounter"
func (sr *SqliteRepository) PopulateGraphTypeReciprocalRelationships(graphType pkg.ResourceGraphType, relationships []models.RelatedResource) []models.RelatedResource { func (gr *GormRepository) PopulateGraphTypeReciprocalRelationships(graphType pkg.ResourceGraphType, relationships []models.RelatedResource) []models.RelatedResource {
reciprocalRelationships := []models.RelatedResource{} reciprocalRelationships := []models.RelatedResource{}
//prioritized lists of sources and sinks for the graph. We will use these to determine which resources are "root" nodes. //prioritized lists of sources and sinks for the graph. We will use these to determine which resources are "root" nodes.

View File

@ -3,6 +3,10 @@ package database
import ( import (
"context" "context"
"fmt" "fmt"
"strconv"
"strings"
"time"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models" "github.com/fastenhealth/fasten-onprem/backend/pkg/models"
databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database" databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database"
"github.com/iancoleman/strcase" "github.com/iancoleman/strcase"
@ -10,9 +14,6 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"gorm.io/gorm" "gorm.io/gorm"
"strconv"
"strings"
"time"
) )
type SearchParameterType string type SearchParameterType string
@ -52,9 +53,9 @@ const TABLE_ALIAS = "fhir"
// ) // )
// AND (user_id = "6efcd7c5-3f29-4f0d-926d-a66ff68bbfc2") // AND (user_id = "6efcd7c5-3f29-4f0d-926d-a66ff68bbfc2")
// GROUP BY `fhir`.`id` // GROUP BY `fhir`.`id`
func (sr *SqliteRepository) QueryResources(ctx context.Context, query models.QueryResource) (interface{}, error) { func (gr *GormRepository) QueryResources(ctx context.Context, query models.QueryResource) (interface{}, error) {
sqlQuery, err := sr.sqlQueryResources(ctx, query) sqlQuery, err := gr.sqlQueryResources(ctx, query)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -74,7 +75,7 @@ func (sr *SqliteRepository) QueryResources(ctx context.Context, query models.Que
// see QueryResources // see QueryResources
// this function has all the logic, but should only be called directly for testing // this function has all the logic, but should only be called directly for testing
func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.QueryResource) (*gorm.DB, error) { func (gr *GormRepository) sqlQueryResources(ctx context.Context, query models.QueryResource) (*gorm.DB, error) {
//todo, until we actually parse the select statement, we will just return all resources based on "from" //todo, until we actually parse the select statement, we will just return all resources based on "from"
//SECURITY: this is required to ensure that only valid resource types are queried (since it's controlled by the user) //SECURITY: this is required to ensure that only valid resource types are queried (since it's controlled by the user)
@ -134,7 +135,7 @@ func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.
} }
//SECURITY: for safety, we will always add/override the current user_id to the where clause. This is to ensure that the user doesnt attempt to override this value in their own where clause //SECURITY: for safety, we will always add/override the current user_id to the where clause. This is to ensure that the user doesnt attempt to override this value in their own where clause
currentUser, currentUserErr := sr.GetCurrentUser(ctx) currentUser, currentUserErr := gr.GetCurrentUser(ctx)
if currentUserErr != nil { if currentUserErr != nil {
return nil, currentUserErr return nil, currentUserErr
} }
@ -234,7 +235,7 @@ func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.
fromClauses = lo.Uniq(fromClauses) fromClauses = lo.Uniq(fromClauses)
fromClauses = lo.Compact(fromClauses) fromClauses = lo.Compact(fromClauses)
sqlQuery := sr.GormClient.WithContext(ctx). sqlQuery := gr.GormClient.WithContext(ctx).
Select(strings.Join(selectClauses, ", ")). Select(strings.Join(selectClauses, ", ")).
Where(strings.Join(whereClauses, " AND "), whereNamedParameters). Where(strings.Join(whereClauses, " AND "), whereNamedParameters).
Group(groupClause). Group(groupClause).
@ -253,7 +254,7 @@ func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.
} }
/// INTERNAL functionality. These functions are exported for testing, but are not available in the Interface /// INTERNAL functionality. These functions are exported for testing, but are not available in the Interface
//TODO: dont export these, instead use casting to convert the interface to the SqliteRepository struct, then call ehese functions directly //TODO: dont export these, instead use casting to convert the interface to the GormRepository struct, then call ehese functions directly
type SearchParameter struct { type SearchParameter struct {
Name string Name string

View File

@ -3,6 +3,12 @@ package database
import ( import (
"context" "context"
"fmt" "fmt"
"io/ioutil"
"log"
"os"
"strings"
"testing"
"github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg"
mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock" mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus" "github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
@ -12,11 +18,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"gorm.io/gorm" "gorm.io/gorm"
"io/ioutil"
"log"
"os"
"strings"
"testing"
) )
// Define the suite, and absorb the built-in basic suite // Define the suite, and absorb the built-in basic suite
@ -42,6 +43,7 @@ func (suite *RepositorySqlTestSuite) BeforeTest(suiteName, testName string) {
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -71,7 +73,7 @@ func TestRepositorySqlTestSuite(t *testing.T) {
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -108,7 +110,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL() {
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithMultipleWhereConditions() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithMultipleWhereConditions() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -146,7 +148,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithMultipleWhereCon
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -183,7 +185,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveOrderBy
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -218,7 +220,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordOrderByAg
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -255,7 +257,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexOrderByAg
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -292,7 +294,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithPrimitiveCountBy
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -329,7 +331,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithKeywordCountByAg
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -364,7 +366,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithWildcardCountByA
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -401,7 +403,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexCountByAg
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWithOrderByMaxFnAggregation() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWithOrderByMaxFnAggregation() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -441,7 +443,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithComplexGroupByWi
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifier() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifier() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test
@ -478,7 +480,7 @@ func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoMo
func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifierWithLimit() { func (suite *RepositorySqlTestSuite) TestQueryResources_SQL_WithTokenGroupByNoModifierWithLimit() {
//setup //setup
sqliteRepo := suite.TestRepository.(*SqliteRepository) sqliteRepo := suite.TestRepository.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test

View File

@ -2,6 +2,10 @@ package database
import ( import (
"context" "context"
"strings"
"testing"
"time"
"github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg"
mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock" mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus" "github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
@ -9,9 +13,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gorm.io/gorm" "gorm.io/gorm"
"strings"
"testing"
"time"
) )
// mimic tests from https://hl7.org/fhir/r4/search.html#token // mimic tests from https://hl7.org/fhir/r4/search.html#token
@ -259,6 +260,7 @@ func (suite *RepositoryTestSuite) TestQueryResources_SQL() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -270,7 +272,7 @@ func (suite *RepositoryTestSuite) TestQueryResources_SQL() {
err = dbRepo.CreateUser(context.Background(), userModel) err = dbRepo.CreateUser(context.Background(), userModel)
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
sqliteRepo := dbRepo.(*SqliteRepository) sqliteRepo := dbRepo.(*GormRepository)
sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true}) sqliteRepo.GormClient = sqliteRepo.GormClient.Session(&gorm.Session{DryRun: true})
//test //test

View File

@ -3,19 +3,20 @@ package database
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models" "github.com/fastenhealth/fasten-onprem/backend/pkg/models"
"github.com/google/uuid" "github.com/google/uuid"
) )
// LoadSettings will retrieve settings from the database, store them in the AppConfig object, and return a Settings struct // LoadSettings will retrieve settings from the database, store them in the AppConfig object, and return a Settings struct
func (sr *SqliteRepository) LoadUserSettings(ctx context.Context) (*models.UserSettings, error) { func (gr *GormRepository) LoadUserSettings(ctx context.Context) (*models.UserSettings, error) {
currentUser, currentUserErr := sr.GetCurrentUser(ctx) currentUser, currentUserErr := gr.GetCurrentUser(ctx)
if currentUserErr != nil { if currentUserErr != nil {
return nil, currentUserErr return nil, currentUserErr
} }
settingsEntries := []models.UserSettingEntry{} settingsEntries := []models.UserSettingEntry{}
if err := sr.GormClient. if err := gr.GormClient.
WithContext(ctx). WithContext(ctx).
Where(models.UserSettingEntry{ Where(models.UserSettingEntry{
UserID: currentUser.ID, UserID: currentUser.ID,
@ -38,8 +39,8 @@ func (sr *SqliteRepository) LoadUserSettings(ctx context.Context) (*models.UserS
// testing // testing
// curl -d '{"metrics": { "notify_level": 5, "status_filter_attributes": 5, "status_threshold": 5 }}' -H "Content-Type: application/json" -X POST http://localhost:9090/api/settings // curl -d '{"metrics": { "notify_level": 5, "status_filter_attributes": 5, "status_threshold": 5 }}' -H "Content-Type: application/json" -X POST http://localhost:9090/api/settings
// SaveSettings will update settings in AppConfig object, then save the settings to the database. // SaveSettings will update settings in AppConfig object, then save the settings to the database.
func (sr *SqliteRepository) SaveUserSettings(ctx context.Context, newSettings *models.UserSettings) error { func (gr *GormRepository) SaveUserSettings(ctx context.Context, newSettings *models.UserSettings) error {
currentUser, currentUserErr := sr.GetCurrentUser(ctx) currentUser, currentUserErr := gr.GetCurrentUser(ctx)
if currentUserErr != nil { if currentUserErr != nil {
return currentUserErr return currentUserErr
} }
@ -47,7 +48,7 @@ func (sr *SqliteRepository) SaveUserSettings(ctx context.Context, newSettings *m
//retrieve current settings from the database //retrieve current settings from the database
currentSettingsEntries := []models.UserSettingEntry{} currentSettingsEntries := []models.UserSettingEntry{}
if err := sr.GormClient. if err := gr.GormClient.
WithContext(ctx). WithContext(ctx).
Where(models.UserSettingEntry{ Where(models.UserSettingEntry{
UserID: currentUser.ID, UserID: currentUser.ID,
@ -66,8 +67,8 @@ func (sr *SqliteRepository) SaveUserSettings(ctx context.Context, newSettings *m
for ndx, settingsEntry := range newSettingsEntries { for ndx, settingsEntry := range newSettingsEntries {
// store in database. // store in database.
//TODO: this should be `sr.gormClient.Updates(&settingsEntries).Error` //TODO: this should be `gr.gormClient.Updates(&settingsEntries).Error`
err := sr.GormClient. err := gr.GormClient.
WithContext(ctx). WithContext(ctx).
Model(&models.UserSettingEntry{}). Model(&models.UserSettingEntry{}).
Where([]uuid.UUID{settingsEntry.ID}). Where([]uuid.UUID{settingsEntry.ID}).
@ -80,7 +81,7 @@ func (sr *SqliteRepository) SaveUserSettings(ctx context.Context, newSettings *m
return nil return nil
} }
func (sr *SqliteRepository) PopulateDefaultUserSettings(ctx context.Context, userId uuid.UUID) error { func (gr *GormRepository) PopulateDefaultUserSettings(ctx context.Context, userId uuid.UUID) error {
//retrieve current settings from the database //retrieve current settings from the database
settingsEntries := []models.UserSettingEntry{} settingsEntries := []models.UserSettingEntry{}
@ -92,6 +93,6 @@ func (sr *SqliteRepository) PopulateDefaultUserSettings(ctx context.Context, use
SettingValueArray: []string{}, SettingValueArray: []string{},
}) })
return sr.GormClient.WithContext(ctx).Create(settingsEntries).Error return gr.GormClient.WithContext(ctx).Create(settingsEntries).Error
} }

View File

@ -3,6 +3,13 @@ package database
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"log"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/fastenhealth/fasten-onprem/backend/pkg" "github.com/fastenhealth/fasten-onprem/backend/pkg"
mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock" mock_config "github.com/fastenhealth/fasten-onprem/backend/pkg/config/mock"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus" "github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
@ -18,18 +25,12 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"golang.org/x/net/context" "golang.org/x/net/context"
"io/ioutil"
"log"
"net/http/httptest"
"os"
"testing"
"time"
) )
func TestSourceCredentialInterface(t *testing.T) { func TestSourceCredentialInterface(t *testing.T) {
t.Parallel() t.Parallel()
repo := new(SqliteRepository) repo := new(GormRepository)
//assert //assert
require.Implements(t, (*sourceModels.DatabaseRepository)(nil), repo, "should implement the DatabaseRepository interface from fasten-sources") require.Implements(t, (*sourceModels.DatabaseRepository)(nil), repo, "should implement the DatabaseRepository interface from fasten-sources")
@ -74,6 +75,7 @@ func (suite *RepositoryTestSuite) TestNewRepository() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
//test //test
@ -87,6 +89,7 @@ func (suite *RepositoryTestSuite) TestCreateUser() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -107,6 +110,7 @@ func (suite *RepositoryTestSuite) TestCreateUser_WithExitingUser_ShouldFail() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -135,6 +139,7 @@ func (suite *RepositoryTestSuite) TestCreateUser_WithUserProvidedId_ShouldBeRepl
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -160,6 +165,7 @@ func (suite *RepositoryTestSuite) TestGetUserByUsername() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -183,6 +189,7 @@ func (suite *RepositoryTestSuite) TestGetUserByUsername_WithInvalidUsername() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -205,6 +212,7 @@ func (suite *RepositoryTestSuite) TestGetCurrentUser_WithContextBackgroundAuthUs
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -229,6 +237,7 @@ func (suite *RepositoryTestSuite) TestGetCurrentUser_WithGinContextBackgroundAut
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -257,6 +266,7 @@ func (suite *RepositoryTestSuite) TestGetCurrentUser_WithContextBackgroundAuthUs
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -273,6 +283,7 @@ func (suite *RepositoryTestSuite) TestCreateGlossaryEntry() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -308,6 +319,7 @@ func (suite *RepositoryTestSuite) TestUpsertRawResource() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -364,6 +376,7 @@ func (suite *RepositoryTestSuite) TestUpsertRawResource_WithRelatedResourceAndDu
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -411,6 +424,7 @@ func (suite *RepositoryTestSuite) TestListResources() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -513,6 +527,7 @@ func (suite *RepositoryTestSuite) TestGetResourceByResourceTypeAndId() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -566,6 +581,7 @@ func (suite *RepositoryTestSuite) TestGetResourceBySourceId() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -619,6 +635,7 @@ func (suite *RepositoryTestSuite) TestGetPatientForSources() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -675,6 +692,7 @@ func (suite *RepositoryTestSuite) TestAddResourceAssociation() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -711,6 +729,7 @@ func (suite *RepositoryTestSuite) TestAddResourceAssociation_WithMismatchingSour
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -760,6 +779,7 @@ func (suite *RepositoryTestSuite) TestRemoveResourceAssociation() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -801,6 +821,7 @@ func (suite *RepositoryTestSuite) TestGetSourceSummary() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -881,6 +902,7 @@ func (suite *RepositoryTestSuite) TestGetSummary() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -984,6 +1006,7 @@ func (suite *RepositoryTestSuite) TestAddResourceComposition() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -1069,6 +1092,7 @@ func (suite *RepositoryTestSuite) TestAddResourceComposition_WithExistingComposi
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -1229,6 +1253,7 @@ func (suite *RepositoryTestSuite) TestCreateBackgroundJob_Sync() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -1263,6 +1288,7 @@ func (suite *RepositoryTestSuite) TestListBackgroundJobs() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)
@ -1339,6 +1365,7 @@ func (suite *RepositoryTestSuite) TestUpdateBackgroundJob() {
//setup //setup
fakeConfig := mock_config.NewMockInterface(suite.MockCtrl) fakeConfig := mock_config.NewMockInterface(suite.MockCtrl)
fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() fakeConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
fakeConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() fakeConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer()) dbRepo, err := NewRepository(fakeConfig, logrus.WithField("test", suite.T().Name()), event_bus.NewNoopEventBusServer())
require.NoError(suite.T(), err) require.NoError(suite.T(), err)

View File

@ -0,0 +1,75 @@
package database
import (
"fmt"
"strings"
"github.com/fastenhealth/fasten-onprem/backend/pkg/config"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models"
databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database"
"github.com/sirupsen/logrus"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func newPostgresRepository(appConfig config.Interface, globalLogger logrus.FieldLogger, eventBus event_bus.Interface) (DatabaseRepository, error) {
//backgroundContext := context.Background()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gorm/PostgreSQL setup
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
globalLogger.Infof("Trying to connect to postgres db: %s\n", appConfig.GetString("database.location"))
dsn := appConfig.GetString("database.location")
database, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
//TODO: figure out how to log database queries again.
//logger: logger
DisableForeignKeyConstraintWhenMigrating: true,
})
if strings.ToUpper(appConfig.GetString("log.level")) == "DEBUG" {
database = database.Debug() //set debug globally
}
if err != nil {
return nil, fmt.Errorf("Failed to connect to database! - %v", err)
}
globalLogger.Infof("Successfully connected to fasten postgres db: %s\n", dsn)
fastenRepo := GormRepository{
AppConfig: appConfig,
Logger: globalLogger,
GormClient: database,
EventBus: eventBus,
}
//TODO: automigrate for now, this should be replaced with a migration tool once the DB has stabilized.
err = fastenRepo.Migrate()
if err != nil {
return nil, err
}
//automigrate Fhir Resource Tables
err = databaseModel.Migrate(fastenRepo.GormClient)
if err != nil {
return nil, err
}
// create/update admin user
//TODO: determine if this admin user is ncessary
//SECURITY: validate this user is necessary
adminUser := models.User{}
err = database.FirstOrCreate(&adminUser, models.User{Username: "admin"}).Error
if err != nil {
return nil, fmt.Errorf("Failed to create admin user! - %v", err)
}
//fail any Locked jobs. This is necessary because the job may have been locked by a process that was killed.
err = fastenRepo.CancelAllLockedBackgroundJobsAndFail()
if err != nil {
return nil, err
}
return &fastenRepo, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -17,3 +17,10 @@ type ConfigValidationError string
func (str ConfigValidationError) Error() string { func (str ConfigValidationError) Error() string {
return fmt.Sprintf("ConfigValidationError: %q", string(str)) return fmt.Sprintf("ConfigValidationError: %q", string(str))
} }
// Raised when the database type is unsupported
type DatabaseTypeNotSupportedError string
func (str DatabaseTypeNotSupportedError) Error() string {
return fmt.Sprintf("DatabaseTypeNotSupportedError: %q", string(str))
}

View File

@ -6,13 +6,17 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/dave/jennifer/jen"
"github.com/iancoleman/strcase"
"golang.org/x/exp/slices"
"io/ioutil" "io/ioutil"
"log" "log"
"os"
"sort" "sort"
"strings" "strings"
"github.com/dave/jennifer/jen"
"github.com/fastenhealth/fasten-onprem/backend/pkg/config"
"github.com/fastenhealth/fasten-onprem/backend/pkg/errors"
"github.com/iancoleman/strcase"
"golang.org/x/exp/slices"
) )
type SearchParameter struct { type SearchParameter struct {
@ -47,6 +51,22 @@ PLEASE DO NOT EDIT BY HAND
`, "\n"), "\n") `, "\n"), "\n")
func main() { func main() {
// Read config file for database type
appconfig, err := config.Create()
if err != nil {
fmt.Printf("FATAL: %+v\n", err)
os.Exit(1)
}
// Find and read the config file
err = appconfig.ReadConfig("../../../../config.yaml")
if _, ok := err.(errors.ConfigFileMissingError); ok { // Handle errors reading the config file
//ignore "could not find config file"
} else if err != nil {
os.Exit(1)
}
databaseType := appconfig.GetString("database.type")
// Read the search-parameters.json file // Read the search-parameters.json file
searchParamsData, err := ioutil.ReadFile("search-parameters.json") searchParamsData, err := ioutil.ReadFile("search-parameters.json")
if err != nil { if err != nil {
@ -188,10 +208,18 @@ func main() {
golangFieldStatement = g.Id(fieldName).Id(golangFieldType) golangFieldStatement = g.Id(fieldName).Id(golangFieldType)
} }
} }
if databaseType == "sqlite" {
golangFieldStatement.Tag(map[string]string{ golangFieldStatement.Tag(map[string]string{
"json": fmt.Sprintf("%s,omitempty", strcase.ToLowerCamel(fieldName)), "json": fmt.Sprintf("%s,omitempty", strcase.ToLowerCamel(fieldName)),
"gorm": fmt.Sprintf("column:%s;%s", strcase.ToLowerCamel(fieldName), mapGormType(fieldInfo.FieldType)), "gorm": fmt.Sprintf("column:%s;%s", strcase.ToLowerCamel(fieldName), mapGormTypeSqlite(fieldInfo.FieldType)),
}) })
} else {
golangFieldStatement.Tag(map[string]string{
"json": fmt.Sprintf("%s,omitempty", strcase.ToLowerCamel(fieldName)),
"gorm": fmt.Sprintf("column:%s;%s", strcase.ToLowerCamel(fieldName), mapGormTypePostgres(fieldInfo.FieldType)),
})
}
} }
}) })
@ -663,7 +691,7 @@ func mapFieldType(fieldType string) string {
} }
// https://www.sqlite.org/datatype3.html // https://www.sqlite.org/datatype3.html
func mapGormType(fieldType string) string { func mapGormTypeSqlite(fieldType string) string {
// gorm:"type:text;serializer:json" // gorm:"type:text;serializer:json"
switch fieldType { switch fieldType {
@ -687,3 +715,26 @@ func mapGormType(fieldType string) string {
return "type:text" return "type:text"
} }
} }
func mapGormTypePostgres(fieldType string) string {
switch fieldType {
case "number":
return "type:real"
case "token":
return "type:text;serializer:json"
case "reference":
return "type:text;serializer:json"
case "date":
return "type:timestamptz"
case "string":
return "type:text;serializer:json"
case "uri":
return "type:text"
case "special":
return "type:text;serializer:json"
case "quantity":
return "type:text;serializer:json"
default:
return "type:text"
}
}

View File

@ -51,6 +51,7 @@ func (suite *SourceHandlerTestSuite) BeforeTest(suiteName, testName string) {
appConfig := mock_config.NewMockInterface(suite.MockCtrl) appConfig := mock_config.NewMockInterface(suite.MockCtrl)
appConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes() appConfig.EXPECT().GetString("database.location").Return(suite.TestDatabase.Name()).AnyTimes()
appConfig.EXPECT().GetString("database.type").Return("sqlite").AnyTimes()
appConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes() appConfig.EXPECT().GetString("log.level").Return("INFO").AnyTimes()
suite.AppConfig = appConfig suite.AppConfig = appConfig

View File

@ -20,7 +20,8 @@ web:
frontend: frontend:
path: /opt/fasten/web path: /opt/fasten/web
database: database:
location: '/opt/fasten/db/fasten.db' type: 'sqlite' # postgres also supported, but still experimental changes
location: '/opt/fasten/db/fasten.db' # if postgres use a DSN, eg. `host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=required TimeZone=Asia/Shanghai`
log: log:
file: '' # absolute or relative paths allowed, eg. web.log file: '' # absolute or relative paths allowed, eg. web.log
level: INFO level: INFO

9
go.mod
View File

@ -27,7 +27,13 @@ require (
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17
golang.org/x/net v0.14.0 golang.org/x/net v0.14.0
gorm.io/datatypes v1.0.7 gorm.io/datatypes v1.0.7
gorm.io/gorm v1.24.1 gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55
)
require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.3 // indirect
) )
require ( require (
@ -104,6 +110,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.3.2 // indirect gorm.io/driver/mysql v1.3.2 // indirect
gorm.io/driver/postgres v1.5.3
modernc.org/libc v1.19.0 // indirect modernc.org/libc v1.19.0 // indirect
modernc.org/mathutil v1.5.0 // indirect modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.4.0 // indirect modernc.org/memory v1.4.0 // indirect

8
go.sum
View File

@ -470,6 +470,8 @@ github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5
github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
@ -482,6 +484,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w=
github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
@ -1286,6 +1290,8 @@ gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I=
gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U=
gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ= gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ=
gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw= gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw=
gorm.io/driver/postgres v1.5.3 h1:qKGY5CPHOuj47K/VxbCXJfFvIUeqMSXXadqdCY+MbBU=
gorm.io/driver/postgres v1.5.3/go.mod h1:F+LtvlFhZT7UBiA81mC9W6Su3D4WUhSboc/36QZU0gk=
gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk=
gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg=
gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI=
@ -1295,6 +1301,8 @@ gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.1 h1:CgvzRniUdG67hBAzsxDGOAuq4Te1osVMYsa1eQbd4fs= gorm.io/gorm v1.24.1 h1:CgvzRniUdG67hBAzsxDGOAuq4Te1osVMYsa1eQbd4fs=
gorm.io/gorm v1.24.1/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.1/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ=
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=