diff --git a/amqp/amqpclient.go b/amqp/amqpclient.go index 3618ced..996309a 100644 --- a/amqp/amqpclient.go +++ b/amqp/amqpclient.go @@ -25,6 +25,7 @@ import ( "encoding/json" "fmt" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" + "github.com/gin-gonic/gin" "github.com/streadway/amqp" "github.com/tidwall/gjson" "log" @@ -203,3 +204,37 @@ func CheckConnection() error { return nil } + +func StartAMQP(AMQPurl string, api *gin.RouterGroup) error { + if AMQPurl != "" { + log.Println("Starting AMQP client") + + err := ConnectAMQP(AMQPurl) + if err != nil { + return err + } + + // register IC action endpoint only if AMQP client is used + RegisterAMQPEndpoint(api.Group("/ic")) + + // Periodically call the Ping function to check which ICs are still there + ticker := time.NewTicker(10 * time.Second) + go func() { + + for { + select { + case <-ticker.C: + err = PingAMQP() + if err != nil { + log.Println("AMQP Error: ", err.Error()) + } + } + } + + }() + + log.Printf("Connected AMQP client to %s", AMQPurl) + } + + return nil +} diff --git a/configuration/config.go b/configuration/config.go index 3297828..65765ee 100644 --- a/configuration/config.go +++ b/configuration/config.go @@ -23,10 +23,9 @@ package configuration import ( "flag" + "github.com/zpatrick/go-config" "log" "os" - - "github.com/zpatrick/go-config" ) // Global configuration @@ -109,9 +108,48 @@ func InitConfig() error { settings, _ := GolbalConfig.Settings() log.Print("All settings:") for key, val := range settings { + // TODO password settings should be excluded! log.Printf(" %s = %s \n", key, val) } } return nil } + +func ConfigureBackend() (string, string, string, string, string, string, string, error) { + + err := InitConfig() + if err != nil { + log.Printf("Error during initialization of global configuration: %v, aborting.", err.Error()) + return "", "", "", "", "", "", "", err + } + + mode, err := GolbalConfig.String("mode") + if err != nil { + log.Printf("Error reading mode from global configuration: %v, aborting.", err.Error()) + return "", "", "", "", "", "", "", err + } + + baseHost, err := GolbalConfig.String("base.host") + if err != nil { + log.Printf("Error reading base.host from global configuration: %v, aborting.", err.Error()) + return "", "", "", "", "", "", "", err + } + basePath, err := GolbalConfig.String("base.path") + if err != nil { + log.Printf("Error reading base.path from global configuration: %v, aborting.", err.Error()) + return "", "", "", "", "", "", "", err + } + port, err := GolbalConfig.String("port") + if err != nil { + log.Printf("Error reading port from global configuration: %v, aborting.", err.Error()) + return "", "", "", "", "", "", "", err + } + + AMQPhost, _ := GolbalConfig.String("amqp.host") + AMQPuser, _ := GolbalConfig.String("amqp.user") + AMQPpass, _ := GolbalConfig.String("amqp.pass") + + return mode, baseHost, basePath, port, AMQPhost, AMQPuser, AMQPpass, nil + +} diff --git a/database/database_test.go b/database/database_test.go index 5fd360b..cfbd640 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -23,7 +23,7 @@ package database import ( "fmt" - "log" + "github.com/zpatrick/go-config" "os" "testing" @@ -32,40 +32,77 @@ import ( ) func TestMain(m *testing.M) { - err := configuration.InitConfig() - if err != nil { - panic(m) - } - - err = InitDB(configuration.GolbalConfig) - if err != nil { - panic(m) - } - - // Verify that you can connect to the database - err = DBpool.DB().Ping() - if err != nil { - log.Panic("Error: DB must ping to run tests") - } defer DBpool.Close() os.Exit(m.Run()) } +func TestInitDB(t *testing.T) { + + err := configuration.InitConfig() + assert.NoError(t, err) + + static := map[string]string{} + mappings := map[string]string{} + + defaults := config.NewStatic(static) + env := config.NewEnvironment(mappings) + + ownconfig := config.NewConfig([]config.Provider{defaults, env}) + + err = InitDB(ownconfig) + assert.Error(t, err) + dbname, err := configuration.GolbalConfig.String("db.name") + assert.NoError(t, err) + static["db.name"] = dbname + ownconfig = config.NewConfig([]config.Provider{defaults, env}) + err = InitDB(ownconfig) + assert.Error(t, err) + + dbhost, err := configuration.GolbalConfig.String("db.host") + assert.NoError(t, err) + static["db.host"] = dbhost + ownconfig = config.NewConfig([]config.Provider{defaults, env}) + err = InitDB(ownconfig) + assert.Error(t, err) + + dbuser, err := configuration.GolbalConfig.String("db.user") + static["db.user"] = dbuser + ownconfig = config.NewConfig([]config.Provider{defaults, env}) + err = InitDB(ownconfig) + assert.Error(t, err) + + dbpass, err := configuration.GolbalConfig.String("db.pass") + static["db.pass"] = dbpass + ownconfig = config.NewConfig([]config.Provider{defaults, env}) + err = InitDB(ownconfig) + assert.Error(t, err) + + dbssl, err := configuration.GolbalConfig.String("db.ssl") + assert.NoError(t, err) + static["db.ssl"] = dbssl + ownconfig = config.NewConfig([]config.Provider{defaults, env}) + err = InitDB(ownconfig) + assert.NoError(t, err) + + // Verify that you can connect to the database + db := GetDB() + err = db.DB().Ping() + assert.NoError(t, err) +} + func TestUserAssociations(t *testing.T) { DropTables() MigrateModels() // create copies of global test data - scenarioA := ScenarioA - scenarioB := ScenarioB - user0 := User0 - userA := UserA - userB := UserB + scenarioA := Scenario{} + scenarioB := Scenario{} + userA := User{Username: "abcdef"} + userB := User{Username: "ghijkl"} - // add three users to DB - assert.NoError(t, DBpool.Create(&user0).Error) // Admin + // add users to DB assert.NoError(t, DBpool.Create(&userA).Error) // Normal User assert.NoError(t, DBpool.Create(&userB).Error) // Normal User @@ -78,11 +115,9 @@ func TestUserAssociations(t *testing.T) { assert.NoError(t, DBpool.Model(&userA).Association("Scenarios").Append(&scenarioA).Error) assert.NoError(t, DBpool.Model(&userA).Association("Scenarios").Append(&scenarioB).Error) assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioA).Error) - assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioB).Error) var usr1 User - assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 2).Error, fmt.Sprintf("Find User with ID=2")) - assert.EqualValues(t, "User_A", usr1.Username) + assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 1).Error, fmt.Sprintf("Find User with ID=1")) // Get scenarios of usr1 var scenarios []Scenario @@ -99,22 +134,20 @@ func TestScenarioAssociations(t *testing.T) { MigrateModels() // create copies of global test data - scenarioA := ScenarioA - scenarioB := ScenarioB - user0 := User0 - userA := UserA - userB := UserB - configA := ConfigA - configB := ConfigB - dashboardA := DashboardA - dashboardB := DashboardB + scenarioA := Scenario{} + scenarioB := Scenario{} + userA := User{Username: "abcdef"} + userB := User{Username: "ghijkl"} + configA := ComponentConfiguration{} + configB := ComponentConfiguration{} + dashboardA := Dashboard{} + dashboardB := Dashboard{} // add scenarios to DB assert.NoError(t, DBpool.Create(&scenarioA).Error) assert.NoError(t, DBpool.Create(&scenarioB).Error) // add users to DB - assert.NoError(t, DBpool.Create(&user0).Error) // Admin assert.NoError(t, DBpool.Create(&userA).Error) // Normal User assert.NoError(t, DBpool.Create(&userB).Error) // Normal User @@ -143,7 +176,6 @@ func TestScenarioAssociations(t *testing.T) { var scenario1 Scenario assert.NoError(t, DBpool.Find(&scenario1, 1).Error, fmt.Sprintf("Find Scenario with ID=1")) - assert.EqualValues(t, "Scenario_A", scenario1.Name) // Get users of scenario1 var users []User @@ -176,10 +208,10 @@ func TestICAssociations(t *testing.T) { MigrateModels() // create copies of global test data - icA := ICA - icB := ICB - configA := ConfigA - configB := ConfigB + icA := InfrastructureComponent{} + icB := InfrastructureComponent{} + configA := ComponentConfiguration{} + configB := ComponentConfiguration{} // add ICs to DB assert.NoError(t, DBpool.Create(&icA).Error) @@ -195,7 +227,6 @@ func TestICAssociations(t *testing.T) { var ic1 InfrastructureComponent assert.NoError(t, DBpool.Find(&ic1, 1).Error, fmt.Sprintf("Find InfrastructureComponent with ID=1")) - assert.EqualValues(t, "xxx.yyy.zzz.aaa", ic1.Host) // Get Component Configurations of ic1 var configs []ComponentConfiguration @@ -212,18 +243,18 @@ func TestComponentConfigurationAssociations(t *testing.T) { MigrateModels() // create copies of global test data - configA := ConfigA - configB := ConfigB - outSignalA := OutSignalA - outSignalB := OutSignalB - inSignalA := InSignalA - inSignalB := InSignalB - fileA := FileA - fileB := FileB - fileC := FileC - fileD := FileD - icA := ICA - icB := ICB + configA := ComponentConfiguration{} + configB := ComponentConfiguration{} + outSignalA := Signal{Direction: "out"} + outSignalB := Signal{Direction: "out"} + inSignalA := Signal{Direction: "in"} + inSignalB := Signal{Direction: "in"} + fileA := File{} + fileB := File{} + fileC := File{} + fileD := File{} + icA := InfrastructureComponent{} + icB := InfrastructureComponent{} // add Component Configurations to DB assert.NoError(t, DBpool.Create(&configA).Error) @@ -261,7 +292,6 @@ func TestComponentConfigurationAssociations(t *testing.T) { var config1 ComponentConfiguration assert.NoError(t, DBpool.Find(&config1, 1).Error, fmt.Sprintf("Find ComponentConfiguration with ID=1")) - assert.EqualValues(t, ConfigA.Name, config1.Name) // Check IC ID if config1.ICID != 1 { @@ -291,10 +321,10 @@ func TestDashboardAssociations(t *testing.T) { MigrateModels() // create copies of global test data - dashboardA := DashboardA - dashboardB := DashboardB - widgetA := WidgetA - widgetB := WidgetB + dashboardA := Dashboard{} + dashboardB := Dashboard{} + widgetA := Widget{} + widgetB := Widget{} // add dashboards to DB assert.NoError(t, DBpool.Create(&dashboardA).Error) @@ -310,7 +340,6 @@ func TestDashboardAssociations(t *testing.T) { var dashboard1 Dashboard assert.NoError(t, DBpool.Find(&dashboard1, 1).Error, fmt.Sprintf("Find Dashboard with ID=1")) - assert.EqualValues(t, "Dashboard_A", dashboard1.Name) //Get widgets of dashboard1 var widgets []Widget @@ -327,12 +356,12 @@ func TestWidgetAssociations(t *testing.T) { MigrateModels() // create copies of global test data - widgetA := WidgetA - widgetB := WidgetB - fileA := FileA - fileB := FileB - fileC := FileC - fileD := FileD + widgetA := Widget{} + widgetB := Widget{} + fileA := File{} + fileB := File{} + fileC := File{} + fileD := File{} // add widgets to DB assert.NoError(t, DBpool.Create(&widgetA).Error) @@ -350,7 +379,6 @@ func TestWidgetAssociations(t *testing.T) { var widget1 Widget assert.NoError(t, DBpool.Find(&widget1, 1).Error, fmt.Sprintf("Find Widget with ID=1")) - assert.EqualValues(t, widgetA.Name, widget1.Name) // Get files of widget var files []File @@ -367,10 +395,10 @@ func TestFileAssociations(t *testing.T) { MigrateModels() // create copies of global test data - fileA := FileA - fileB := FileB - fileC := FileC - fileD := FileD + fileA := File{} + fileB := File{} + fileC := File{} + fileD := File{} // add files to DB assert.NoError(t, DBpool.Create(&fileA).Error) @@ -380,19 +408,4 @@ func TestFileAssociations(t *testing.T) { var file1 File assert.NoError(t, DBpool.Find(&file1, 1).Error, fmt.Sprintf("Find File with ID=1")) - assert.EqualValues(t, "File_A", file1.Name) -} - -func TestAddAdmin(t *testing.T) { - DropTables() - MigrateModels() - - assert.NoError(t, DBAddAdminUser()) -} - -func TestAddAdminAndUsers(t *testing.T) { - DropTables() - MigrateModels() - - assert.NoError(t, DBAddAdminAndUserAndGuest()) } diff --git a/database/testdata.go b/database/testdata.go deleted file mode 100644 index f77f684..0000000 --- a/database/testdata.go +++ /dev/null @@ -1,548 +0,0 @@ -/** Database package, test data. -* -* @author Sonja Happ -* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC -* @license GNU General Public License (version 3) -* -* VILLASweb-backend-go -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*********************************************************************************/ -package database - -import ( - "bytes" - "encoding/json" - "fmt" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" - "github.com/gin-gonic/gin" - "github.com/jinzhu/gorm/dialects/postgres" - "golang.org/x/crypto/bcrypt" - "io" - "mime/multipart" - "net/http" - "net/http/httptest" - "os" - "time" -) - -// ####################################################################### -// #################### Data used for testing ############################ -// ####################################################################### - -// Users -var StrPassword0 = "xyz789" -var StrPasswordA = "abc123" -var StrPasswordB = "bcd234" -var StrPasswordC = "guestpw" - -// Hash passwords with bcrypt algorithm -var bcryptCost = 10 -var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost) -var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost) -var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost) -var pwC, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordC), bcryptCost) - -var User0 = User{Username: "User_0", Password: string(pw0), - Role: "Admin", Mail: "User_0@example.com", Active: true} -var UserA = User{Username: "User_A", Password: string(pwA), - Role: "User", Mail: "User_A@example.com", Active: true} -var UserB = User{Username: "User_B", Password: string(pwB), - Role: "User", Mail: "User_B@example.com", Active: true} -var UserC = User{Username: "User_C", Password: string(pwC), - Role: "Guest", Mail: "User_C@example.com", Active: true} - -type UserRequest struct { - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - OldPassword string `json:"oldPassword,omitempty"` - Mail string `json:"mail,omitempty"` - Role string `json:"role,omitempty"` - Active string `json:"active,omitempty"` -} - -var newUserA = UserRequest{ - Username: UserA.Username, - Password: StrPasswordA, - Role: UserA.Role, - Mail: UserA.Mail, -} - -var newUserB = UserRequest{ - Username: UserB.Username, - Password: StrPasswordB, - Role: UserB.Role, - Mail: UserB.Mail, -} - -var newUserC = UserRequest{ - Username: UserC.Username, - Password: StrPasswordC, - Role: UserC.Role, - Mail: UserC.Mail, -} - -// Infrastructure components - -var propertiesA = json.RawMessage(`{"location" : "ACSlab"}`) -var propertiesB = json.RawMessage(`{"location" : "ACSlab"}`) - -var ICA = InfrastructureComponent{ - UUID: "4854af30-325f-44a5-ad59-b67b2597de68", - Host: "xxx.yyy.zzz.aaa", - Type: "DPsim", - Category: "Simulator", - Name: "Test DPsim Simulator", - Uptime: 0, - State: "running", - StateUpdateAt: time.Now().String(), - Properties: postgres.Jsonb{propertiesA}, - RawProperties: postgres.Jsonb{propertiesA}, -} - -var ICB = InfrastructureComponent{ - UUID: "7be0322d-354e-431e-84bd-ae4c9633138b", - Host: "xxx.yyy.zzz.bbb", - Type: "VILLASnode", - Category: "Gateway", - Name: "Test VILLASnode Gateway", - Uptime: 0, - State: "idle", - StateUpdateAt: time.Now().String(), - Properties: postgres.Jsonb{propertiesB}, - RawProperties: postgres.Jsonb{propertiesB}, -} - -// Scenarios - -var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`) -var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`) - -var ScenarioA = Scenario{ - Name: "Scenario_A", - Running: true, - StartParameters: postgres.Jsonb{startParametersA}, -} -var ScenarioB = Scenario{ - Name: "Scenario_B", - Running: false, - StartParameters: postgres.Jsonb{startParametersB}, -} - -// Component Configuration - -var ConfigA = ComponentConfiguration{ - Name: "Example simulation", - StartParameters: postgres.Jsonb{startParametersA}, - SelectedFileID: 3, -} - -var ConfigB = ComponentConfiguration{ - Name: "VILLASnode gateway X", - StartParameters: postgres.Jsonb{startParametersB}, - SelectedFileID: 4, -} - -// Signals - -var OutSignalA = Signal{ - Name: "outSignal_A", - Direction: "out", - Index: 1, - Unit: "V", -} - -var OutSignalB = Signal{ - Name: "outSignal_B", - Direction: "out", - Index: 2, - Unit: "V", -} - -var InSignalA = Signal{ - Name: "inSignal_A", - Direction: "in", - Index: 1, - Unit: "A", -} - -var InSignalB = Signal{ - Name: "inSignal_B", - Direction: "in", - Index: 2, - Unit: "A", -} - -// Dashboards - -var DashboardA = Dashboard{ - Name: "Dashboard_A", - Grid: 15, -} -var DashboardB = Dashboard{ - Name: "Dashboard_B", - Grid: 10, -} - -// Files - -var FileA = File{ - Name: "File_A", - Type: "text/plain", - Size: 42, - Date: time.Now().String(), -} - -var FileB = File{ - Name: "File_B", - Type: "text/plain", - Size: 1234, - Date: time.Now().String(), -} - -var FileC = File{ - Name: "File_C", - Type: "text/plain", - Size: 32, - Date: time.Now().String(), -} -var FileD = File{ - Name: "File_D", - Type: "text/plain", - Size: 5000, - Date: time.Now().String(), -} - -// Widgets -var customPropertiesA = json.RawMessage(`{"property1" : "testValue1A", "property2" : "testValue2A", "property3" : 42}`) -var customPropertiesBox = json.RawMessage(`{"border_color" : "18", "background_color" : "2", "background_color_opacity" : 0.3}`) -var customPropertiesSlider = json.RawMessage(`{"default_value" : 10, "orientation" : 0, "rangeMin" : 0, "rangeMax": 500, "step" : 1}`) -var customPropertiesLabel = json.RawMessage(`{"textSize" : "20", "fontColor" : 5}`) -var customPropertiesButton = json.RawMessage(`{"toggle" : "Value1", "on_value" : "Value2", "off_value" : Value3}`) -var customPropertiesCustomActions = json.RawMessage(`{"actions" : "Value1", "icon" : "Value2"}`) -var customPropertiesGauge = json.RawMessage(`{ "valueMin": 0, "valueMax": 1}`) -var customPropertiesLamp = json.RawMessage(`{"signal" : 0, "on_color" : 4, "off_color": 2 , "threshold" : 0.5}`) - -var WidgetA = Widget{ - Name: "Label", - Type: "Label", - Width: 100, - Height: 50, - MinHeight: 40, - MinWidth: 80, - X: 10, - Y: 10, - Z: 200, - IsLocked: false, - CustomProperties: postgres.Jsonb{customPropertiesLabel}, - SignalIDs: []int64{1}, -} - -var WidgetB = Widget{ - Name: "Slider", - Type: "Slider", - Width: 200, - Height: 20, - MinHeight: 10, - MinWidth: 50, - X: 70, - Y: 10, - Z: 0, - IsLocked: false, - CustomProperties: postgres.Jsonb{customPropertiesSlider}, - SignalIDs: []int64{1}, -} - -var WidgetC = Widget{ - Name: "Box", - Type: "Box", - Width: 200, - Height: 200, - MinHeight: 10, - MinWidth: 50, - X: 300, - Y: 10, - Z: 0, - IsLocked: false, - CustomProperties: postgres.Jsonb{customPropertiesBox}, - SignalIDs: []int64{3}, -} - -var WidgetD = Widget{ - Name: "Action", - Type: "Action", - Width: 20, - Height: 20, - MinHeight: 10, - MinWidth: 50, - X: 10, - Y: 50, - Z: 0, - IsLocked: false, - CustomProperties: postgres.Jsonb{customPropertiesCustomActions}, - SignalIDs: []int64{2}, -} - -var WidgetE = Widget{ - Name: "Lamp", - Type: "Lamp", - Width: 200, - Height: 20, - MinHeight: 10, - MinWidth: 50, - X: 50, - Y: 300, - Z: 0, - IsLocked: false, - CustomProperties: postgres.Jsonb{customPropertiesLamp}, - SignalIDs: []int64{4}, -} - -func DBAddAdminUser() error { - DBpool.AutoMigrate(&User{}) - - // Check if admin user exists in DB - var users []User - err := DBpool.Where("Role = ?", "Admin").Find(&users).Error - - if len(users) == 0 { - fmt.Println("No admin user found in DB, adding default admin user.") - //create a copy of global test data - user0 := User0 - // add admin user to DB - err = DBpool.Create(&user0).Error - } - - return err -} - -func DBAddAdminAndUserAndGuest() error { - DBpool.AutoMigrate(&User{}) - - //create a copy of global test data - user0 := User0 - userA := UserA - userB := UserB - userC := UserC - - // add admin user to DB - err := DBpool.Create(&user0).Error - // add normal users to DB - err = DBpool.Create(&userA).Error - err = DBpool.Create(&userB).Error - // add guest user to DB - err = DBpool.Create(&userC).Error - return err -} - -// Populates DB with test data -func DBAddTestData(basePath string, router *gin.Engine) error { - - MigrateModels() - // Create entries of each model (data defined in testdata.go) - // add Admin user - err := DBAddAdminUser() - if err != nil { - return err - } - - // authenticate as admin - token, err := helper.AuthenticateForTest(router, basePath+"/authenticate", "POST", helper.AdminCredentials) - if err != nil { - return err - } - - // add 2 normal and 1 guest user - code, _, err := helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": newUserA}) - if code != http.StatusOK { - return fmt.Errorf("error adding User_A") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": newUserB}) - if code != http.StatusOK { - return fmt.Errorf("error adding User_B") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": newUserC}) - if code != http.StatusOK { - return fmt.Errorf("error adding User_C") - } - - // add infrastructure components - code, _, err = helper.TestEndpoint(router, token, basePath+"/ic", "POST", helper.KeyModels{"ic": ICA}) - if code != http.StatusOK { - return fmt.Errorf("error adding IC A") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/ic", "POST", helper.KeyModels{"ic": ICB}) - if code != http.StatusOK { - return fmt.Errorf("error adding IC B") - } - - // add scenarios - code, _, err = helper.TestEndpoint(router, token, basePath+"/scenarios", "POST", helper.KeyModels{"scenario": ScenarioA}) - if code != http.StatusOK { - return fmt.Errorf("error adding Scenario A") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/scenarios", "POST", helper.KeyModels{"scenario": ScenarioB}) - if code != http.StatusOK { - return fmt.Errorf("error adding Scenario B") - } - - // add users to scenario - code, _, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/1/user?username=User_A", basePath), "PUT", nil) - if code != http.StatusOK { - return fmt.Errorf("error adding User_A to Scenario A") - } - code, _, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/2/user?username=User_A", basePath), "PUT", nil) - if code != http.StatusOK { - return fmt.Errorf("error adding User_A to Scenario B") - } - code, _, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/2/user?username=User_B", basePath), "PUT", nil) - if code != http.StatusOK { - return fmt.Errorf("error adding User_B to Scenario B") - } - code, _, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/1/user?username=User_C", basePath), "PUT", nil) - if code != http.StatusOK { - return fmt.Errorf("error adding User_C to Scenario A") - } - - // add component configurations - configA := ConfigA - configB := ConfigB - configA.ScenarioID = 1 - configB.ScenarioID = 1 - configA.ICID = 1 - configB.ICID = 2 - code, _, err = helper.TestEndpoint(router, token, basePath+"/configs", "POST", helper.KeyModels{"config": configA}) - if code != http.StatusOK { - return fmt.Errorf("error adding Config A") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/configs", "POST", helper.KeyModels{"config": configB}) - if code != http.StatusOK { - return fmt.Errorf("error adding Config B") - } - - // add dashboards - dashboardA := DashboardA - dashboardB := DashboardB - dashboardA.ScenarioID = 1 - dashboardB.ScenarioID = 1 - code, _, err = helper.TestEndpoint(router, token, basePath+"/dashboards", "POST", helper.KeyModels{"dashboard": dashboardA}) - if code != http.StatusOK { - return fmt.Errorf("error adding Dashboard B") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/dashboards", "POST", helper.KeyModels{"dashboard": dashboardB}) - if code != http.StatusOK { - return fmt.Errorf("error adding Dashboard B") - } - - // add widgets - widgetA := WidgetA - widgetB := WidgetB - widgetC := WidgetC - widgetD := WidgetD - widgetE := WidgetE - widgetA.DashboardID = 1 - widgetB.DashboardID = 1 - widgetC.DashboardID = 1 - widgetD.DashboardID = 1 - widgetE.DashboardID = 1 - code, _, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetA}) - if code != http.StatusOK { - return fmt.Errorf("error adding Widget A") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetB}) - if code != http.StatusOK { - return fmt.Errorf("error adding Widget B") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetC}) - if code != http.StatusOK { - return fmt.Errorf("error adding Widget C") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetD}) - if code != http.StatusOK { - return fmt.Errorf("error adding Widget D") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetE}) - if code != http.StatusOK { - return fmt.Errorf("error adding Widget E") - } - - // add signals - outSignalA := OutSignalA - outSignalB := OutSignalB - inSignalA := InSignalA - inSignalB := InSignalB - outSignalA.ConfigID = 1 - outSignalB.ConfigID = 1 - inSignalA.ConfigID = 1 - inSignalB.ConfigID = 1 - code, _, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": outSignalB}) - if code != http.StatusOK { - return fmt.Errorf("error adding outSignalB") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": outSignalA}) - if code != http.StatusOK { - return fmt.Errorf("error adding outSignalA") - } - - code, _, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": inSignalA}) - if code != http.StatusOK { - return fmt.Errorf("error adding inSignalA") - } - code, _, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": inSignalB}) - if code != http.StatusOK { - return fmt.Errorf("error adding inSignalB") - } - - // upload files - - // upload readme file - bodyBuf := &bytes.Buffer{} - bodyWriter := multipart.NewWriter(bodyBuf) - fileWriter, _ := bodyWriter.CreateFormFile("file", "Readme.md") - fh, _ := os.Open("README.md") - defer fh.Close() - - // io copy - _, err = io.Copy(fileWriter, fh) - contentType := bodyWriter.FormDataContentType() - bodyWriter.Close() - - // Create the request and add file to component config - w1 := httptest.NewRecorder() - req1, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=config", bodyBuf) - req1.Header.Set("Content-Type", contentType) - req1.Header.Add("Authorization", "Bearer "+token) - router.ServeHTTP(w1, req1) - - // upload image file - bodyBuf = &bytes.Buffer{} - bodyWriter = multipart.NewWriter(bodyBuf) - fileWriter, _ = bodyWriter.CreateFormFile("file", "logo.png") - fh, _ = os.Open("doc/pictures/villas_web.png") - defer fh.Close() - - // io copy - _, err = io.Copy(fileWriter, fh) - contentType = bodyWriter.FormDataContentType() - bodyWriter.Close() - - // Create the request and add file to widget - w2 := httptest.NewRecorder() - req2, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=widget", bodyBuf) - req2.Header.Set("Content-Type", contentType) - req2.Header.Add("Authorization", "Bearer "+token) - router.ServeHTTP(w2, req2) - - return nil -} diff --git a/helper/test_data.go b/helper/test_data.go new file mode 100644 index 0000000..1e873f5 --- /dev/null +++ b/helper/test_data.go @@ -0,0 +1,342 @@ +/** Helper package, test data. +* +* @author Sonja Happ +* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC +* @license GNU General Public License (version 3) +* +* VILLASweb-backend-go +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*********************************************************************************/ +package helper + +import ( + "encoding/json" + "fmt" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" + "github.com/jinzhu/gorm/dialects/postgres" + "golang.org/x/crypto/bcrypt" + "time" +) + +// ####################################################################### +// #################### Data used for testing ############################ +// ####################################################################### + +// Credentials +var StrPassword0 = "xyz789" +var StrPasswordA = "abc123" +var StrPasswordB = "bcd234" +var StrPasswordC = "guestpw" + +// Hash passwords with bcrypt algorithm +var bcryptCost = 10 +var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost) +var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost) +var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost) +var pwC, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordC), bcryptCost) + +var User0 = database.User{Username: "User_0", Password: string(pw0), + Role: "Admin", Mail: "User_0@example.com", Active: true} +var UserA = database.User{Username: "User_A", Password: string(pwA), + Role: "User", Mail: "User_A@example.com", Active: true} +var UserB = database.User{Username: "User_B", Password: string(pwB), + Role: "User", Mail: "User_B@example.com", Active: true} +var UserC = database.User{Username: "User_C", Password: string(pwC), + Role: "Guest", Mail: "User_C@example.com", Active: true} + +type UserRequest struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + OldPassword string `json:"oldPassword,omitempty"` + Mail string `json:"mail,omitempty"` + Role string `json:"role,omitempty"` + Active string `json:"active,omitempty"` +} + +var NewUserA = UserRequest{ + Username: UserA.Username, + Password: StrPasswordA, + Role: UserA.Role, + Mail: UserA.Mail, +} + +var NewUserB = UserRequest{ + Username: UserB.Username, + Password: StrPasswordB, + Role: UserB.Role, + Mail: UserB.Mail, +} + +var NewUserC = UserRequest{ + Username: UserC.Username, + Password: StrPasswordC, + Role: UserC.Role, + Mail: UserC.Mail, +} + +// Infrastructure components + +var propertiesA = json.RawMessage(`{"location" : "ACSlab"}`) +var propertiesB = json.RawMessage(`{"location" : "ACSlab"}`) + +var ICA = database.InfrastructureComponent{ + UUID: "4854af30-325f-44a5-ad59-b67b2597de68", + Host: "xxx.yyy.zzz.aaa", + Type: "DPsim", + Category: "Simulator", + Name: "Test DPsim Simulator", + Uptime: 0, + State: "running", + StateUpdateAt: time.Now().String(), + Properties: postgres.Jsonb{propertiesA}, + RawProperties: postgres.Jsonb{propertiesA}, +} + +var ICB = database.InfrastructureComponent{ + UUID: "7be0322d-354e-431e-84bd-ae4c9633138b", + Host: "xxx.yyy.zzz.bbb", + Type: "VILLASnode", + Category: "Gateway", + Name: "Test VILLASnode Gateway", + Uptime: 0, + State: "idle", + StateUpdateAt: time.Now().String(), + Properties: postgres.Jsonb{propertiesB}, + RawProperties: postgres.Jsonb{propertiesB}, +} + +// Scenarios + +var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`) +var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`) + +var ScenarioA = database.Scenario{ + Name: "Scenario_A", + Running: true, + StartParameters: postgres.Jsonb{startParametersA}, +} +var ScenarioB = database.Scenario{ + Name: "Scenario_B", + Running: false, + StartParameters: postgres.Jsonb{startParametersB}, +} + +// Component Configuration + +var ConfigA = database.ComponentConfiguration{ + Name: "Example simulation", + StartParameters: postgres.Jsonb{startParametersA}, + SelectedFileID: 3, +} + +var ConfigB = database.ComponentConfiguration{ + Name: "VILLASnode gateway X", + StartParameters: postgres.Jsonb{startParametersB}, + SelectedFileID: 4, +} + +// Signals + +var OutSignalA = database.Signal{ + Name: "outSignal_A", + Direction: "out", + Index: 1, + Unit: "V", +} + +var OutSignalB = database.Signal{ + Name: "outSignal_B", + Direction: "out", + Index: 2, + Unit: "V", +} + +var InSignalA = database.Signal{ + Name: "inSignal_A", + Direction: "in", + Index: 1, + Unit: "A", +} + +var InSignalB = database.Signal{ + Name: "inSignal_B", + Direction: "in", + Index: 2, + Unit: "A", +} + +// Dashboards + +var DashboardA = database.Dashboard{ + Name: "Dashboard_A", + Grid: 15, +} +var DashboardB = database.Dashboard{ + Name: "Dashboard_B", + Grid: 10, +} + +// Files + +var FileA = database.File{ + Name: "File_A", + Type: "text/plain", + Size: 42, + Date: time.Now().String(), +} + +var FileB = database.File{ + Name: "File_B", + Type: "text/plain", + Size: 1234, + Date: time.Now().String(), +} + +var FileC = database.File{ + Name: "File_C", + Type: "text/plain", + Size: 32, + Date: time.Now().String(), +} +var FileD = database.File{ + Name: "File_D", + Type: "text/plain", + Size: 5000, + Date: time.Now().String(), +} + +// Widgets +var customPropertiesA = json.RawMessage(`{"property1" : "testValue1A", "property2" : "testValue2A", "property3" : 42}`) +var customPropertiesBox = json.RawMessage(`{"border_color" : "18", "background_color" : "2", "background_color_opacity" : 0.3}`) +var customPropertiesSlider = json.RawMessage(`{"default_value" : 10, "orientation" : 0, "rangeMin" : 0, "rangeMax": 500, "step" : 1}`) +var customPropertiesLabel = json.RawMessage(`{"textSize" : "20", "fontColor" : 5}`) +var customPropertiesButton = json.RawMessage(`{"toggle" : "Value1", "on_value" : "Value2", "off_value" : Value3}`) +var customPropertiesCustomActions = json.RawMessage(`{"actions" : "Value1", "icon" : "Value2"}`) +var customPropertiesGauge = json.RawMessage(`{ "valueMin": 0, "valueMax": 1}`) +var customPropertiesLamp = json.RawMessage(`{"signal" : 0, "on_color" : 4, "off_color": 2 , "threshold" : 0.5}`) + +var WidgetA = database.Widget{ + Name: "Label", + Type: "Label", + Width: 100, + Height: 50, + MinHeight: 40, + MinWidth: 80, + X: 10, + Y: 10, + Z: 200, + IsLocked: false, + CustomProperties: postgres.Jsonb{customPropertiesLabel}, + SignalIDs: []int64{1}, +} + +var WidgetB = database.Widget{ + Name: "Slider", + Type: "Slider", + Width: 200, + Height: 20, + MinHeight: 10, + MinWidth: 50, + X: 70, + Y: 10, + Z: 0, + IsLocked: false, + CustomProperties: postgres.Jsonb{customPropertiesSlider}, + SignalIDs: []int64{1}, +} + +var WidgetC = database.Widget{ + Name: "Box", + Type: "Box", + Width: 200, + Height: 200, + MinHeight: 10, + MinWidth: 50, + X: 300, + Y: 10, + Z: 0, + IsLocked: false, + CustomProperties: postgres.Jsonb{customPropertiesBox}, + SignalIDs: []int64{3}, +} + +var WidgetD = database.Widget{ + Name: "Action", + Type: "Action", + Width: 20, + Height: 20, + MinHeight: 10, + MinWidth: 50, + X: 10, + Y: 50, + Z: 0, + IsLocked: false, + CustomProperties: postgres.Jsonb{customPropertiesCustomActions}, + SignalIDs: []int64{2}, +} + +var WidgetE = database.Widget{ + Name: "Lamp", + Type: "Lamp", + Width: 200, + Height: 20, + MinHeight: 10, + MinWidth: 50, + X: 50, + Y: 300, + Z: 0, + IsLocked: false, + CustomProperties: postgres.Jsonb{customPropertiesLamp}, + SignalIDs: []int64{4}, +} + +// add a default admin user to the DB +func DBAddAdminUser() error { + database.DBpool.AutoMigrate(&database.User{}) + + // Check if admin user exists in DB + var users []database.User + err := database.DBpool.Where("Role = ?", "Admin").Find(&users).Error + + if len(users) == 0 { + fmt.Println("No admin user found in DB, adding default admin user.") + //create a copy of global test data + user0 := User0 + // add admin user to DB + err = database.DBpool.Create(&user0).Error + } + + return err +} + +// add default admin user, normal users and a guest to the DB +func DBAddAdminAndUserAndGuest() error { + database.DBpool.AutoMigrate(&database.User{}) + + //create a copy of global test data + user0 := User0 + userA := UserA + userB := UserB + userC := UserC + + // add admin user to DB + err := database.DBpool.Create(&user0).Error + // add normal users to DB + err = database.DBpool.Create(&userA).Error + err = database.DBpool.Create(&userB).Error + // add guest user to DB + err = database.DBpool.Create(&userC).Error + return err +} diff --git a/helper/test_utilities.go b/helper/test_utilities.go index 75940c1..0d2d1cb 100644 --- a/helper/test_utilities.go +++ b/helper/test_utilities.go @@ -39,12 +39,6 @@ type KeyModels map[string]interface{} // #################### User data used for testing ####################### // ####################################################################### -// Credentials -var StrPassword0 = "xyz789" -var StrPasswordA = "abc123" -var StrPasswordB = "bcd234" -var StrPasswordC = "guestpw" - type Credentials struct { Username string Password string diff --git a/routes/component-configuration/config_test.go b/routes/component-configuration/config_test.go index cb252e2..f7ff7c4 100644 --- a/routes/component-configuration/config_test.go +++ b/routes/component-configuration/config_test.go @@ -72,13 +72,13 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) { // POST $newICA newICA := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } _, resp, _ := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICA}) @@ -88,13 +88,13 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) { // POST a second IC to change to that IC during testing newICB := ICRequest{ - UUID: database.ICB.UUID, - Host: database.ICB.Host, - Type: database.ICB.Type, - Name: database.ICB.Name, - Category: database.ICB.Category, - State: database.ICB.State, - Properties: database.ICB.Properties, + UUID: helper.ICB.UUID, + Host: helper.ICB.Host, + Type: helper.ICB.Type, + Name: helper.ICB.Name, + Category: helper.ICB.Category, + State: helper.ICB.State, + Properties: helper.ICB.Properties, } _, resp, _ = helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICB}) @@ -105,9 +105,9 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) { // POST $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } _, resp, _ = helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -153,7 +153,7 @@ func TestMain(m *testing.M) { func TestAddConfig(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -161,11 +161,11 @@ func TestAddConfig(t *testing.T) { scenarioID, ICID := addScenarioAndIC() newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: scenarioID, ICID: ICID, - StartParameters: database.ConfigA.StartParameters, - SelectedFileID: database.ConfigA.SelectedFileID, + StartParameters: helper.ConfigA.StartParameters, + SelectedFileID: helper.ConfigA.SelectedFileID, } // authenticate as normal userB who has no access to new scenario @@ -249,7 +249,7 @@ func TestUpdateConfig(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -263,11 +263,11 @@ func TestUpdateConfig(t *testing.T) { // test POST newConfig newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: scenarioID, ICID: ICID, - StartParameters: database.ConfigA.StartParameters, - SelectedFileID: database.ConfigA.SelectedFileID, + StartParameters: helper.ConfigA.StartParameters, + SelectedFileID: helper.ConfigA.SelectedFileID, } code, resp, err := helper.TestEndpoint(router, token, base_api_configs, "POST", helper.KeyModels{"config": newConfig}) @@ -279,8 +279,8 @@ func TestUpdateConfig(t *testing.T) { assert.NoError(t, err) updatedConfig := ConfigRequest{ - Name: database.ConfigB.Name, - StartParameters: database.ConfigB.StartParameters, + Name: helper.ConfigB.Name, + StartParameters: helper.ConfigB.StartParameters, } // authenticate as normal userB who has no access to new scenario @@ -361,7 +361,7 @@ func TestUpdateConfig(t *testing.T) { func TestDeleteConfig(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -369,11 +369,11 @@ func TestDeleteConfig(t *testing.T) { scenarioID, ICID := addScenarioAndIC() newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: scenarioID, ICID: ICID, - StartParameters: database.ConfigA.StartParameters, - SelectedFileID: database.ConfigA.SelectedFileID, + StartParameters: helper.ConfigA.StartParameters, + SelectedFileID: helper.ConfigA.SelectedFileID, } // authenticate as normal user @@ -434,7 +434,7 @@ func TestDeleteConfig(t *testing.T) { func TestGetAllConfigsOfScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -448,11 +448,11 @@ func TestGetAllConfigsOfScenario(t *testing.T) { // test POST newConfig newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: scenarioID, ICID: ICID, - StartParameters: database.ConfigA.StartParameters, - SelectedFileID: database.ConfigA.SelectedFileID, + StartParameters: helper.ConfigA.StartParameters, + SelectedFileID: helper.ConfigA.SelectedFileID, } code, resp, err := helper.TestEndpoint(router, token, base_api_configs, "POST", helper.KeyModels{"config": newConfig}) diff --git a/routes/dashboard/dashboard_test.go b/routes/dashboard/dashboard_test.go index 3040323..83ce190 100644 --- a/routes/dashboard/dashboard_test.go +++ b/routes/dashboard/dashboard_test.go @@ -54,9 +54,9 @@ func addScenario(token string) (scenarioID uint) { // POST $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } _, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -101,7 +101,7 @@ func TestMain(m *testing.M) { func TestAddDashboard(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -112,8 +112,8 @@ func TestAddDashboard(t *testing.T) { // test POST dashboards/ $newDashboard newDashboard := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: scenarioID, } code, resp, err := helper.TestEndpoint(router, token, @@ -187,7 +187,7 @@ func TestAddDashboard(t *testing.T) { func TestUpdateDashboard(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -198,8 +198,8 @@ func TestUpdateDashboard(t *testing.T) { // test POST dashboards/ $newDashboard newDashboard := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: scenarioID, } code, resp, err := helper.TestEndpoint(router, token, @@ -212,8 +212,8 @@ func TestUpdateDashboard(t *testing.T) { assert.NoError(t, err) updatedDashboard := DashboardRequest{ - Name: database.DashboardB.Name, - Grid: database.DashboardB.Grid, + Name: helper.DashboardB.Name, + Grid: helper.DashboardB.Grid, } // authenticate as guest user @@ -268,7 +268,7 @@ func TestUpdateDashboard(t *testing.T) { func TestDeleteDashboard(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -279,8 +279,8 @@ func TestDeleteDashboard(t *testing.T) { // test POST dashboards/ $newDashboard newDashboard := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: scenarioID, } code, resp, err := helper.TestEndpoint(router, token, @@ -341,7 +341,7 @@ func TestDeleteDashboard(t *testing.T) { func TestGetAllDashboardsOfScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -357,8 +357,8 @@ func TestGetAllDashboardsOfScenario(t *testing.T) { // test POST dashboards/ $newDashboard newDashboardA := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: scenarioID, } code, resp, err := helper.TestEndpoint(router, token, @@ -368,8 +368,8 @@ func TestGetAllDashboardsOfScenario(t *testing.T) { // POST a second dashboard for the same scenario newDashboardB := DashboardRequest{ - Name: database.DashboardB.Name, - Grid: database.DashboardB.Grid, + Name: helper.DashboardB.Name, + Grid: helper.DashboardB.Grid, ScenarioID: scenarioID, } code, resp, err = helper.TestEndpoint(router, token, diff --git a/routes/file/file_test.go b/routes/file/file_test.go index d47ee93..533d9cf 100644 --- a/routes/file/file_test.go +++ b/routes/file/file_test.go @@ -99,13 +99,13 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin // POST $newICA newICA := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } _, resp, _ := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICA}) @@ -119,9 +119,9 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin // POST $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } _, resp, _ = helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -131,10 +131,10 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin // POST new component config newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: uint(newScenarioID), ICID: uint(newICID), - StartParameters: database.ConfigA.StartParameters, + StartParameters: helper.ConfigA.StartParameters, } _, resp, _ = helper.TestEndpoint(router, token, "/api/configs", "POST", helper.KeyModels{"config": newConfig}) @@ -144,8 +144,8 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin // POST new dashboard newDashboard := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: uint(newScenarioID), } _, resp, _ = helper.TestEndpoint(router, token, @@ -156,17 +156,17 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin // POST new widget newWidget := WidgetRequest{ - Name: database.WidgetA.Name, - Type: database.WidgetA.Type, - Width: database.WidgetA.Width, - Height: database.WidgetA.Height, - MinWidth: database.WidgetA.MinWidth, - MinHeight: database.WidgetA.MinHeight, - X: database.WidgetA.X, - Y: database.WidgetA.Y, - Z: database.WidgetA.Z, - IsLocked: database.WidgetA.IsLocked, - CustomProperties: database.WidgetA.CustomProperties, + Name: helper.WidgetA.Name, + Type: helper.WidgetA.Type, + Width: helper.WidgetA.Width, + Height: helper.WidgetA.Height, + MinWidth: helper.WidgetA.MinWidth, + MinHeight: helper.WidgetA.MinHeight, + X: helper.WidgetA.X, + Y: helper.WidgetA.Y, + Z: helper.WidgetA.Z, + IsLocked: helper.WidgetA.IsLocked, + CustomProperties: helper.WidgetA.CustomProperties, DashboardID: uint(newDashboardID), } _, resp, _ = helper.TestEndpoint(router, token, @@ -222,7 +222,7 @@ func TestMain(m *testing.M) { func TestAddFile(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // using the respective endpoints of the API @@ -338,7 +338,7 @@ func TestUpdateFile(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // using the respective endpoints of the API @@ -472,7 +472,7 @@ func TestUpdateFile(t *testing.T) { func TestDeleteFile(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // using the respective endpoints of the API @@ -623,7 +623,7 @@ func TestGetAllFilesOfConfig(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // using the respective endpoints of the API diff --git a/routes/infrastructure-component/ic_test.go b/routes/infrastructure-component/ic_test.go index fe53081..92abc5e 100644 --- a/routes/infrastructure-component/ic_test.go +++ b/routes/infrastructure-component/ic_test.go @@ -73,7 +73,7 @@ func TestMain(m *testing.M) { func TestAddICAsAdmin(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -90,7 +90,7 @@ func TestAddICAsAdmin(t *testing.T) { // try to POST malformed IC (required fields missing, validation should fail) // should result in an unprocessable entity newMalformedIC := ICRequest{ - UUID: database.ICB.UUID, + UUID: helper.ICB.UUID, } code, resp, err = helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newMalformedIC}) @@ -99,13 +99,13 @@ func TestAddICAsAdmin(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err = helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newIC}) @@ -142,7 +142,7 @@ func TestAddICAsAdmin(t *testing.T) { func TestAddICAsUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as user token, err := helper.AuthenticateForTest(router, @@ -151,13 +151,13 @@ func TestAddICAsUser(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } // This should fail with unprocessable entity 422 error code @@ -171,7 +171,7 @@ func TestAddICAsUser(t *testing.T) { func TestUpdateICAsAdmin(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -180,13 +180,13 @@ func TestUpdateICAsAdmin(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newIC}) @@ -235,7 +235,7 @@ func TestUpdateICAsAdmin(t *testing.T) { func TestUpdateICAsUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -244,13 +244,13 @@ func TestUpdateICAsUser(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newIC}) @@ -279,7 +279,7 @@ func TestUpdateICAsUser(t *testing.T) { func TestDeleteICAsAdmin(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -288,13 +288,13 @@ func TestDeleteICAsAdmin(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newIC}) @@ -331,7 +331,7 @@ func TestDeleteICAsAdmin(t *testing.T) { func TestDeleteICAsUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -340,13 +340,13 @@ func TestDeleteICAsUser(t *testing.T) { // test POST ic/ $newIC newIC := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newIC}) @@ -374,7 +374,7 @@ func TestDeleteICAsUser(t *testing.T) { func TestGetAllICs(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -388,13 +388,13 @@ func TestGetAllICs(t *testing.T) { // test POST ic/ $newICA newICA := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICA}) @@ -403,13 +403,13 @@ func TestGetAllICs(t *testing.T) { // test POST ic/ $newICB newICB := ICRequest{ - UUID: database.ICB.UUID, - Host: database.ICB.Host, - Type: database.ICB.Type, - Name: database.ICB.Name, - Category: database.ICB.Category, - State: database.ICB.State, - Properties: database.ICB.Properties, + UUID: helper.ICB.UUID, + Host: helper.ICB.Host, + Type: helper.ICB.Type, + Name: helper.ICB.Name, + Category: helper.ICB.Category, + State: helper.ICB.State, + Properties: helper.ICB.Properties, } code, resp, err = helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICB}) @@ -439,7 +439,7 @@ func TestGetAllICs(t *testing.T) { func TestGetConfigsOfIC(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -448,13 +448,13 @@ func TestGetConfigsOfIC(t *testing.T) { // test POST ic/ $newICA newICA := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } code, resp, err := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICA}) diff --git a/routes/register.go b/routes/register.go new file mode 100644 index 0000000..f6a8ad3 --- /dev/null +++ b/routes/register.go @@ -0,0 +1,275 @@ +/** Routes package, registration function +* +* @author Sonja Happ +* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC +* @license GNU General Public License (version 3) +* +* VILLASweb-backend-go +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*********************************************************************************/ + +package routes + +import ( + "bytes" + "fmt" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" + component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/healthz" + infrastructure_component "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/infrastructure-component" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/metrics" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/signal" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" + "github.com/gin-gonic/gin" + ginSwagger "github.com/swaggo/gin-swagger" + "github.com/swaggo/gin-swagger/swaggerFiles" + "io" + "mime/multipart" + "net/http" + "net/http/httptest" + "os" +) + +// register all backend endpoints; to be called after DB is initialized +func RegisterEndpoints(router *gin.Engine, api *gin.RouterGroup) { + + healthz.RegisterHealthzEndpoint(api.Group("/healthz")) + metrics.RegisterMetricsEndpoint(api.Group("/metrics")) + // All endpoints (except for /healthz and /metrics) require authentication except when someone wants to + // login (POST /authenticate) + user.RegisterAuthenticate(api.Group("/authenticate")) + + api.Use(user.Authentication(true)) + + scenario.RegisterScenarioEndpoints(api.Group("/scenarios")) + component_configuration.RegisterComponentConfigurationEndpoints(api.Group("/configs")) + signal.RegisterSignalEndpoints(api.Group("/signals")) + dashboard.RegisterDashboardEndpoints(api.Group("/dashboards")) + widget.RegisterWidgetEndpoints(api.Group("/widgets")) + file.RegisterFileEndpoints(api.Group("/files")) + user.RegisterUserEndpoints(api.Group("/users")) + infrastructure_component.RegisterICEndpoints(api.Group("/ic")) + + router.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + + metrics.InitCounters() + +} + +// Uses API endpoints to add test data to the backend; All endpoints have to be registered before invoking this function. +func AddTestData(basePath string, router *gin.Engine) (*bytes.Buffer, error) { + + database.MigrateModels() + // Create entries of each model (data defined in test_data.go) + // add Admin user + err := helper.DBAddAdminUser() + if err != nil { + return nil, err + } + + // authenticate as admin + token, err := helper.AuthenticateForTest(router, basePath+"/authenticate", "POST", helper.AdminCredentials) + if err != nil { + return nil, err + } + + // add 2 normal and 1 guest user + code, resp, err := helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": helper.NewUserA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_A") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": helper.NewUserB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_B") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/users", "POST", helper.KeyModels{"user": helper.NewUserC}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_C") + } + + // add infrastructure components + code, resp, err = helper.TestEndpoint(router, token, basePath+"/ic", "POST", helper.KeyModels{"ic": helper.ICA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding IC A") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/ic", "POST", helper.KeyModels{"ic": helper.ICB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding IC B") + } + + // add scenarios + code, resp, err = helper.TestEndpoint(router, token, basePath+"/scenarios", "POST", helper.KeyModels{"scenario": helper.ScenarioA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Scenario A") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/scenarios", "POST", helper.KeyModels{"scenario": helper.ScenarioB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Scenario B") + } + + // add users to scenario + code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/1/user?username=User_A", basePath), "PUT", nil) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_A to Scenario A") + } + code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/2/user?username=User_A", basePath), "PUT", nil) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_A to Scenario B") + } + code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/2/user?username=User_B", basePath), "PUT", nil) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_B to Scenario B") + } + code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("%v/scenarios/1/user?username=User_C", basePath), "PUT", nil) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding User_C to Scenario A") + } + + // add component configurations + configA := helper.ConfigA + configB := helper.ConfigB + configA.ScenarioID = 1 + configB.ScenarioID = 1 + configA.ICID = 1 + configB.ICID = 2 + code, resp, err = helper.TestEndpoint(router, token, basePath+"/configs", "POST", helper.KeyModels{"config": configA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Config A") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/configs", "POST", helper.KeyModels{"config": configB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Config B") + } + + // add dashboards + dashboardA := helper.DashboardA + dashboardB := helper.DashboardB + dashboardA.ScenarioID = 1 + dashboardB.ScenarioID = 1 + code, resp, err = helper.TestEndpoint(router, token, basePath+"/dashboards", "POST", helper.KeyModels{"dashboard": dashboardA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Dashboard B") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/dashboards", "POST", helper.KeyModels{"dashboard": dashboardB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Dashboard B") + } + + // add widgets + widgetA := helper.WidgetA + widgetB := helper.WidgetB + widgetC := helper.WidgetC + widgetD := helper.WidgetD + widgetE := helper.WidgetE + widgetA.DashboardID = 1 + widgetB.DashboardID = 1 + widgetC.DashboardID = 1 + widgetD.DashboardID = 1 + widgetE.DashboardID = 1 + code, resp, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Widget A") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Widget B") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetC}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Widget C") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetD}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Widget D") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/widgets", "POST", helper.KeyModels{"widget": widgetE}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding Widget E") + } + + // add signals + outSignalA := helper.OutSignalA + outSignalB := helper.OutSignalB + inSignalA := helper.InSignalA + inSignalB := helper.InSignalB + outSignalA.ConfigID = 1 + outSignalB.ConfigID = 1 + inSignalA.ConfigID = 1 + inSignalB.ConfigID = 1 + code, resp, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": outSignalB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding outSignalB") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": outSignalA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding outSignalA") + } + + code, resp, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": inSignalA}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding inSignalA") + } + code, resp, err = helper.TestEndpoint(router, token, basePath+"/signals", "POST", helper.KeyModels{"signal": inSignalB}) + if code != http.StatusOK { + return resp, fmt.Errorf("error adding inSignalB") + } + + // upload files + + // upload readme file + bodyBuf := &bytes.Buffer{} + bodyWriter := multipart.NewWriter(bodyBuf) + fileWriter, _ := bodyWriter.CreateFormFile("file", "Readme.md") + fh, _ := os.Open("README.md") + defer fh.Close() + + // io copy + _, err = io.Copy(fileWriter, fh) + contentType := bodyWriter.FormDataContentType() + bodyWriter.Close() + + // Create the request and add file to component config + w1 := httptest.NewRecorder() + req1, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=config", bodyBuf) + req1.Header.Set("Content-Type", contentType) + req1.Header.Add("Authorization", "Bearer "+token) + router.ServeHTTP(w1, req1) + + // upload image file + bodyBuf = &bytes.Buffer{} + bodyWriter = multipart.NewWriter(bodyBuf) + fileWriter, _ = bodyWriter.CreateFormFile("file", "logo.png") + fh, _ = os.Open("doc/pictures/villas_web.png") + defer fh.Close() + + // io copy + _, err = io.Copy(fileWriter, fh) + contentType = bodyWriter.FormDataContentType() + bodyWriter.Close() + + // Create the request and add file to widget + w2 := httptest.NewRecorder() + req2, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=widget", bodyBuf) + req2.Header.Set("Content-Type", contentType) + req2.Header.Add("Authorization", "Bearer "+token) + router.ServeHTTP(w2, req2) + + return nil, nil +} diff --git a/routes/register_test.go b/routes/register_test.go new file mode 100644 index 0000000..e8a5445 --- /dev/null +++ b/routes/register_test.go @@ -0,0 +1,64 @@ +/** Routes package, testing +* +* @author Sonja Happ +* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC +* @license GNU General Public License (version 3) +* +* VILLASweb-backend-go +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*********************************************************************************/ + +package routes + +import ( + "git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +var router *gin.Engine + +func TestMain(m *testing.M) { + err := configuration.InitConfig() + if err != nil { + panic(m) + } + + err = database.InitDB(configuration.GolbalConfig) + if err != nil { + panic(m) + } + defer database.DBpool.Close() + + router = gin.Default() + + os.Exit(m.Run()) +} + +func TestRegisterEndpoints(t *testing.T) { + database.DropTables() + database.MigrateModels() + + api := router.Group("/api") + RegisterEndpoints(router, api) +} + +func TestAddTestData(t *testing.T) { + resp, err := AddTestData("/api", router) + assert.NoError(t, err, "Response body: %v", resp) +} diff --git a/routes/scenario/scenario_test.go b/routes/scenario/scenario_test.go index 14c82db..f64a30f 100644 --- a/routes/scenario/scenario_test.go +++ b/routes/scenario/scenario_test.go @@ -79,12 +79,12 @@ func TestAddScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } // authenticate as normal user @@ -181,7 +181,7 @@ func TestUpdateScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -190,9 +190,9 @@ func TestUpdateScenario(t *testing.T) { // test POST scenarios/ $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -209,8 +209,8 @@ func TestUpdateScenario(t *testing.T) { updatedScenario := ScenarioRequest{ Name: "Updated name", - Running: !database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Running: !helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } // try to update with non JSON body @@ -251,7 +251,7 @@ func TestGetAllScenariosAsAdmin(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -270,9 +270,9 @@ func TestGetAllScenariosAsAdmin(t *testing.T) { // test POST scenarios/ $newScenarioB newScenarioB := ScenarioRequest{ - Name: database.ScenarioB.Name, - Running: database.ScenarioB.Running, - StartParameters: database.ScenarioB.StartParameters, + Name: helper.ScenarioB.Name, + Running: helper.ScenarioB.Running, + StartParameters: helper.ScenarioB.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenarioB}) @@ -286,9 +286,9 @@ func TestGetAllScenariosAsAdmin(t *testing.T) { // test POST scenarios/ $newScenarioA newScenarioA := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err = helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenarioA}) @@ -312,7 +312,7 @@ func TestGetAllScenariosAsUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal userB token, err := helper.AuthenticateForTest(router, @@ -326,9 +326,9 @@ func TestGetAllScenariosAsUser(t *testing.T) { // test POST scenarios/ $newScenarioB newScenarioB := ScenarioRequest{ - Name: database.ScenarioB.Name, - Running: database.ScenarioB.Running, - StartParameters: database.ScenarioB.StartParameters, + Name: helper.ScenarioB.Name, + Running: helper.ScenarioB.Running, + StartParameters: helper.ScenarioB.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, @@ -343,9 +343,9 @@ func TestGetAllScenariosAsUser(t *testing.T) { // test POST scenarios/ $newScenarioA newScenarioA := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err = helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenarioA}) @@ -369,7 +369,7 @@ func TestDeleteScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -378,9 +378,9 @@ func TestDeleteScenario(t *testing.T) { // test POST scenarios/ $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -441,7 +441,7 @@ func TestAddUserToScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -450,9 +450,9 @@ func TestAddUserToScenario(t *testing.T) { // test POST scenarios/ $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -500,7 +500,7 @@ func TestAddUserToScenario(t *testing.T) { assert.Equalf(t, 200, code, "Response body: \n%v\n", resp) // Compare resp to userB - err = helper.CompareResponse(resp, helper.KeyModels{"user": database.UserB}) + err = helper.CompareResponse(resp, helper.KeyModels{"user": helper.UserB}) assert.NoError(t, err) // Count AGAIN the number of all the users returned for newScenario @@ -521,7 +521,7 @@ func TestGetAllUsersOfScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -530,9 +530,9 @@ func TestGetAllUsersOfScenario(t *testing.T) { // test POST scenarios/ $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -606,7 +606,7 @@ func TestRemoveUserFromScenario(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -615,9 +615,9 @@ func TestRemoveUserFromScenario(t *testing.T) { // test POST scenarios/ $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } code, resp, err := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -664,7 +664,7 @@ func TestRemoveUserFromScenario(t *testing.T) { assert.Equalf(t, 200, code, "Response body: \n%v\n", resp) // Compare DELETE's response with UserB - err = helper.CompareResponse(resp, helper.KeyModels{"user": database.UserC}) + err = helper.CompareResponse(resp, helper.KeyModels{"user": helper.UserC}) assert.NoError(t, err) // Count AGAIN the number of all the users returned for newScenario diff --git a/routes/signal/signal_test.go b/routes/signal/signal_test.go index 1cf2f58..7c44b58 100644 --- a/routes/signal/signal_test.go +++ b/routes/signal/signal_test.go @@ -78,13 +78,13 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) { // POST $newICA newICA := ICRequest{ - UUID: database.ICA.UUID, - Host: database.ICA.Host, - Type: database.ICA.Type, - Name: database.ICA.Name, - Category: database.ICA.Category, - State: database.ICA.State, - Properties: database.ICA.Properties, + UUID: helper.ICA.UUID, + Host: helper.ICA.Host, + Type: helper.ICA.Type, + Name: helper.ICA.Name, + Category: helper.ICA.Category, + State: helper.ICA.State, + Properties: helper.ICA.Properties, } _, resp, _ := helper.TestEndpoint(router, token, "/api/ic", "POST", helper.KeyModels{"ic": newICA}) @@ -98,9 +98,9 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) { // POST $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } _, resp, _ = helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -110,10 +110,10 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) { // test POST newConfig newConfig := ConfigRequest{ - Name: database.ConfigA.Name, + Name: helper.ConfigA.Name, ScenarioID: uint(newScenarioID), ICID: uint(newICID), - StartParameters: database.ConfigA.StartParameters, + StartParameters: helper.ConfigA.StartParameters, } _, resp, _ = helper.TestEndpoint(router, token, "/api/configs", "POST", helper.KeyModels{"config": newConfig}) @@ -162,7 +162,7 @@ func TestMain(m *testing.M) { func TestAddSignal(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -175,9 +175,9 @@ func TestAddSignal(t *testing.T) { assert.NoError(t, err) newSignal := SignalRequest{ - Name: database.InSignalA.Name, - Unit: database.InSignalA.Unit, - Direction: database.InSignalA.Direction, + Name: helper.InSignalA.Name, + Unit: helper.InSignalA.Unit, + Direction: helper.InSignalA.Direction, Index: 1, ConfigID: configID, } @@ -257,7 +257,7 @@ func TestAddSignal(t *testing.T) { func TestUpdateSignal(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -271,9 +271,9 @@ func TestUpdateSignal(t *testing.T) { // test POST signals/ $newSignal newSignal := SignalRequest{ - Name: database.InSignalA.Name, - Unit: database.InSignalA.Unit, - Direction: database.InSignalA.Direction, + Name: helper.InSignalA.Name, + Unit: helper.InSignalA.Unit, + Direction: helper.InSignalA.Direction, Index: 1, ConfigID: configID, } @@ -287,8 +287,8 @@ func TestUpdateSignal(t *testing.T) { assert.NoError(t, err) updatedSignal := SignalRequest{ - Name: database.InSignalB.Name, - Unit: database.InSignalB.Unit, + Name: helper.InSignalB.Name, + Unit: helper.InSignalB.Unit, Index: 1, } @@ -359,7 +359,7 @@ func TestUpdateSignal(t *testing.T) { func TestDeleteSignal(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -373,9 +373,9 @@ func TestDeleteSignal(t *testing.T) { // test POST signals/ $newSignal newSignal := SignalRequest{ - Name: database.InSignalA.Name, - Unit: database.InSignalA.Unit, - Direction: database.InSignalA.Direction, + Name: helper.InSignalA.Name, + Unit: helper.InSignalA.Unit, + Direction: helper.InSignalA.Direction, Index: 1, ConfigID: configID, } @@ -412,9 +412,9 @@ func TestDeleteSignal(t *testing.T) { // add an output signal to make sure that counting of input signals works newSignalout := SignalRequest{ - Name: database.OutSignalA.Name, - Unit: database.OutSignalA.Unit, - Direction: database.OutSignalA.Direction, + Name: helper.OutSignalA.Name, + Unit: helper.OutSignalA.Unit, + Direction: helper.OutSignalA.Direction, Index: 1, ConfigID: configID, } @@ -454,7 +454,7 @@ func TestDeleteSignal(t *testing.T) { func TestGetAllInputSignalsOfConfig(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // prepare the content of the DB for testing // by adding a scenario and a IC to the DB @@ -473,9 +473,9 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) { // test POST signals/ $newSignal newSignalA := SignalRequest{ - Name: database.InSignalA.Name, - Unit: database.InSignalA.Unit, - Direction: database.InSignalA.Direction, + Name: helper.InSignalA.Name, + Unit: helper.InSignalA.Unit, + Direction: helper.InSignalA.Direction, Index: 1, ConfigID: configID, } @@ -486,9 +486,9 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) { // add a second input signal newSignalB := SignalRequest{ - Name: database.InSignalB.Name, - Unit: database.InSignalB.Unit, - Direction: database.InSignalB.Direction, + Name: helper.InSignalB.Name, + Unit: helper.InSignalB.Unit, + Direction: helper.InSignalB.Direction, Index: 2, ConfigID: configID, } @@ -499,9 +499,9 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) { // add an output signal newSignalAout := SignalRequest{ - Name: database.OutSignalA.Name, - Unit: database.OutSignalA.Unit, - Direction: database.OutSignalA.Direction, + Name: helper.OutSignalA.Name, + Unit: helper.OutSignalA.Unit, + Direction: helper.OutSignalA.Direction, Index: 1, ConfigID: configID, } @@ -512,9 +512,9 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) { // add a second output signal newSignalBout := SignalRequest{ - Name: database.OutSignalB.Name, - Unit: database.OutSignalB.Unit, - Direction: database.OutSignalB.Direction, + Name: helper.OutSignalB.Name, + Unit: helper.OutSignalB.Unit, + Direction: helper.OutSignalB.Direction, Index: 1, ConfigID: configID, } diff --git a/routes/user/user_test.go b/routes/user/user_test.go index 1d87f27..3a878bf 100644 --- a/routes/user/user_test.go +++ b/routes/user/user_test.go @@ -74,7 +74,7 @@ func TestMain(m *testing.M) { func TestAuthenticate(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // try to authenticate with non JSON body // should result in unauthorized @@ -134,7 +134,7 @@ func TestAddGetUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -258,7 +258,7 @@ func TestUsersNotAllowedActions(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -318,7 +318,7 @@ func TestGetAllUsers(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -367,7 +367,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -524,7 +524,7 @@ func TestInvalidUserUpdate(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -597,7 +597,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, @@ -671,7 +671,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { // modify newUser's password, requires admin password modRequest = UserRequest{ Password: "4_g00d_pw!", - OldPassword: database.StrPassword0, + OldPassword: helper.StrPassword0, } code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -716,7 +716,7 @@ func TestDeleteUser(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as admin token, err := helper.AuthenticateForTest(router, diff --git a/routes/widget/widget_test.go b/routes/widget/widget_test.go index 4814b6a..7ea06a4 100644 --- a/routes/widget/widget_test.go +++ b/routes/widget/widget_test.go @@ -70,9 +70,9 @@ func addScenarioAndDashboard(token string) (scenarioID uint, dashboardID uint) { // POST $newScenario newScenario := ScenarioRequest{ - Name: database.ScenarioA.Name, - Running: database.ScenarioA.Running, - StartParameters: database.ScenarioA.StartParameters, + Name: helper.ScenarioA.Name, + Running: helper.ScenarioA.Running, + StartParameters: helper.ScenarioA.StartParameters, } _, resp, _ := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) @@ -82,8 +82,8 @@ func addScenarioAndDashboard(token string) (scenarioID uint, dashboardID uint) { // test POST dashboards/ $newDashboard newDashboard := DashboardRequest{ - Name: database.DashboardA.Name, - Grid: database.DashboardA.Grid, + Name: helper.DashboardA.Name, + Grid: helper.DashboardA.Grid, ScenarioID: uint(newScenarioID), } _, resp, _ = helper.TestEndpoint(router, token, @@ -130,7 +130,7 @@ func TestMain(m *testing.M) { func TestAddWidget(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -140,19 +140,19 @@ func TestAddWidget(t *testing.T) { _, dashboardID := addScenarioAndDashboard(token) newWidget := WidgetRequest{ - Name: database.WidgetA.Name, - Type: database.WidgetA.Type, - Width: database.WidgetA.Width, - Height: database.WidgetA.Height, - MinWidth: database.WidgetA.MinWidth, - MinHeight: database.WidgetA.MinHeight, - X: database.WidgetA.X, - Y: database.WidgetA.Y, - Z: database.WidgetA.Z, - IsLocked: database.WidgetA.IsLocked, - CustomProperties: database.WidgetA.CustomProperties, + Name: helper.WidgetA.Name, + Type: helper.WidgetA.Type, + Width: helper.WidgetA.Width, + Height: helper.WidgetA.Height, + MinWidth: helper.WidgetA.MinWidth, + MinHeight: helper.WidgetA.MinHeight, + X: helper.WidgetA.X, + Y: helper.WidgetA.Y, + Z: helper.WidgetA.Z, + IsLocked: helper.WidgetA.IsLocked, + CustomProperties: helper.WidgetA.CustomProperties, DashboardID: dashboardID, - SignalIDs: database.WidgetA.SignalIDs, + SignalIDs: helper.WidgetA.SignalIDs, } // authenticate as userB who has no access to scenario @@ -230,7 +230,7 @@ func TestAddWidget(t *testing.T) { func TestUpdateWidget(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -241,19 +241,19 @@ func TestUpdateWidget(t *testing.T) { // test POST widgets/ $newWidget newWidget := WidgetRequest{ - Name: database.WidgetA.Name, - Type: database.WidgetA.Type, - Width: database.WidgetA.Width, - Height: database.WidgetA.Height, - MinWidth: database.WidgetA.MinWidth, - MinHeight: database.WidgetA.MinHeight, - X: database.WidgetA.X, - Y: database.WidgetA.Y, - Z: database.WidgetA.Z, - IsLocked: database.WidgetA.IsLocked, - CustomProperties: database.WidgetA.CustomProperties, + Name: helper.WidgetA.Name, + Type: helper.WidgetA.Type, + Width: helper.WidgetA.Width, + Height: helper.WidgetA.Height, + MinWidth: helper.WidgetA.MinWidth, + MinHeight: helper.WidgetA.MinHeight, + X: helper.WidgetA.X, + Y: helper.WidgetA.Y, + Z: helper.WidgetA.Z, + IsLocked: helper.WidgetA.IsLocked, + CustomProperties: helper.WidgetA.CustomProperties, DashboardID: dashboardID, - SignalIDs: database.WidgetA.SignalIDs, + SignalIDs: helper.WidgetA.SignalIDs, } code, resp, err := helper.TestEndpoint(router, token, "/api/widgets", "POST", helper.KeyModels{"widget": newWidget}) @@ -265,14 +265,14 @@ func TestUpdateWidget(t *testing.T) { assert.NoError(t, err) updatedWidget := WidgetRequest{ - Name: database.WidgetB.Name, - Type: database.WidgetB.Type, - Width: database.WidgetB.Width, - Height: database.WidgetB.Height, - MinWidth: database.WidgetB.MinWidth, - MinHeight: database.WidgetB.MinHeight, - CustomProperties: database.WidgetA.CustomProperties, - SignalIDs: database.WidgetB.SignalIDs, + Name: helper.WidgetB.Name, + Type: helper.WidgetB.Type, + Width: helper.WidgetB.Width, + Height: helper.WidgetB.Height, + MinWidth: helper.WidgetB.MinWidth, + MinHeight: helper.WidgetB.MinHeight, + CustomProperties: helper.WidgetA.CustomProperties, + SignalIDs: helper.WidgetB.SignalIDs, } // authenticate as userB who has no access to scenario @@ -342,7 +342,7 @@ func TestUpdateWidget(t *testing.T) { func TestDeleteWidget(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -353,19 +353,19 @@ func TestDeleteWidget(t *testing.T) { // test POST widgets/ $newWidget newWidget := WidgetRequest{ - Name: database.WidgetA.Name, - Type: database.WidgetA.Type, - Width: database.WidgetA.Width, - Height: database.WidgetA.Height, - MinWidth: database.WidgetA.MinWidth, - MinHeight: database.WidgetA.MinHeight, - X: database.WidgetA.X, - Y: database.WidgetA.Y, - Z: database.WidgetA.Z, - IsLocked: database.WidgetA.IsLocked, - CustomProperties: database.WidgetA.CustomProperties, + Name: helper.WidgetA.Name, + Type: helper.WidgetA.Type, + Width: helper.WidgetA.Width, + Height: helper.WidgetA.Height, + MinWidth: helper.WidgetA.MinWidth, + MinHeight: helper.WidgetA.MinHeight, + X: helper.WidgetA.X, + Y: helper.WidgetA.Y, + Z: helper.WidgetA.Z, + IsLocked: helper.WidgetA.IsLocked, + CustomProperties: helper.WidgetA.CustomProperties, DashboardID: dashboardID, - SignalIDs: database.WidgetA.SignalIDs, + SignalIDs: helper.WidgetA.SignalIDs, } code, resp, err := helper.TestEndpoint(router, token, "/api/widgets", "POST", helper.KeyModels{"widget": newWidget}) @@ -419,7 +419,7 @@ func TestDeleteWidget(t *testing.T) { func TestGetAllWidgetsOfDashboard(t *testing.T) { database.DropTables() database.MigrateModels() - assert.NoError(t, database.DBAddAdminAndUserAndGuest()) + assert.NoError(t, helper.DBAddAdminAndUserAndGuest()) // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -452,19 +452,19 @@ func TestGetAllWidgetsOfDashboard(t *testing.T) { // test POST widgets/ $newWidget newWidgetA := WidgetRequest{ - Name: database.WidgetA.Name, - Type: database.WidgetA.Type, - Width: database.WidgetA.Width, - Height: database.WidgetA.Height, - MinWidth: database.WidgetA.MinWidth, - MinHeight: database.WidgetA.MinHeight, - X: database.WidgetA.X, - Y: database.WidgetA.Y, - Z: database.WidgetA.Z, - IsLocked: database.WidgetA.IsLocked, - CustomProperties: database.WidgetA.CustomProperties, + Name: helper.WidgetA.Name, + Type: helper.WidgetA.Type, + Width: helper.WidgetA.Width, + Height: helper.WidgetA.Height, + MinWidth: helper.WidgetA.MinWidth, + MinHeight: helper.WidgetA.MinHeight, + X: helper.WidgetA.X, + Y: helper.WidgetA.Y, + Z: helper.WidgetA.Z, + IsLocked: helper.WidgetA.IsLocked, + CustomProperties: helper.WidgetA.CustomProperties, DashboardID: dashboardID, - SignalIDs: database.WidgetA.SignalIDs, + SignalIDs: helper.WidgetA.SignalIDs, } code, resp, err = helper.TestEndpoint(router, token, "/api/widgets", "POST", helper.KeyModels{"widget": newWidgetA}) @@ -472,19 +472,19 @@ func TestGetAllWidgetsOfDashboard(t *testing.T) { assert.Equalf(t, 200, code, "Response body: \n%v\n", resp) newWidgetB := WidgetRequest{ - Name: database.WidgetB.Name, - Type: database.WidgetB.Type, - Width: database.WidgetB.Width, - Height: database.WidgetB.Height, - MinWidth: database.WidgetB.MinWidth, - MinHeight: database.WidgetB.MinHeight, - X: database.WidgetB.X, - Y: database.WidgetB.Y, - Z: database.WidgetB.Z, - IsLocked: database.WidgetB.IsLocked, - CustomProperties: database.WidgetB.CustomProperties, + Name: helper.WidgetB.Name, + Type: helper.WidgetB.Type, + Width: helper.WidgetB.Width, + Height: helper.WidgetB.Height, + MinWidth: helper.WidgetB.MinWidth, + MinHeight: helper.WidgetB.MinHeight, + X: helper.WidgetB.X, + Y: helper.WidgetB.Y, + Z: helper.WidgetB.Z, + IsLocked: helper.WidgetB.IsLocked, + CustomProperties: helper.WidgetB.CustomProperties, DashboardID: dashboardID, - SignalIDs: database.WidgetB.SignalIDs, + SignalIDs: helper.WidgetB.SignalIDs, } code, resp, err = helper.TestEndpoint(router, token, "/api/widgets", "POST", helper.KeyModels{"widget": newWidgetB}) diff --git a/start.go b/start.go index 6616bed..8bfbc68 100644 --- a/start.go +++ b/start.go @@ -23,163 +23,38 @@ package main import ( "fmt" - component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/healthz" - infrastructure_component "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/infrastructure-component" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/signal" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" - ginSwagger "github.com/swaggo/gin-swagger" - "github.com/swaggo/gin-swagger/swaggerFiles" - "log" - "time" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/amqp" "git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" apidocs "git.rwth-aachen.de/acs/public/villas/web-backend-go/doc/api" // doc/api folder is used by Swag CLI, you have to import it - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/metrics" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes" "github.com/gin-gonic/gin" + "log" ) -func configureBackend() (string, string, string, string, string, string, string, error) { - - err := configuration.InitConfig() - if err != nil { - log.Printf("Error during initialization of global configuration: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - - err = database.InitDB(configuration.GolbalConfig) - if err != nil { - log.Printf("Error during initialization of database: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - - mode, err := configuration.GolbalConfig.String("mode") - if err != nil { - log.Printf("Error reading mode from global configuration: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - - if mode == "release" { - gin.SetMode(gin.ReleaseMode) - } - - baseHost, err := configuration.GolbalConfig.String("base.host") - if err != nil { - log.Printf("Error reading base.host from global configuration: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - basePath, err := configuration.GolbalConfig.String("base.path") - if err != nil { - log.Printf("Error reading base.path from global configuration: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - port, err := configuration.GolbalConfig.String("port") - if err != nil { - log.Printf("Error reading port from global configuration: %v, aborting.", err.Error()) - return "", "", "", "", "", "", "", err - } - - apidocs.SwaggerInfo.Host = baseHost - apidocs.SwaggerInfo.BasePath = basePath - - metrics.InitCounters() - - AMQPhost, _ := configuration.GolbalConfig.String("amqp.host") - AMQPuser, _ := configuration.GolbalConfig.String("amqp.user") - AMQPpass, _ := configuration.GolbalConfig.String("amqp.pass") - - return mode, baseHost, basePath, port, AMQPhost, AMQPuser, AMQPpass, nil - -} - -func registerEndpoints(router *gin.Engine, api *gin.RouterGroup) { - - healthz.RegisterHealthzEndpoint(api.Group("/healthz")) - metrics.RegisterMetricsEndpoint(api.Group("/metrics")) - // All endpoints (except for /healthz and /metrics) require authentication except when someone wants to - // login (POST /authenticate) - user.RegisterAuthenticate(api.Group("/authenticate")) - - api.Use(user.Authentication(true)) - - scenario.RegisterScenarioEndpoints(api.Group("/scenarios")) - component_configuration.RegisterComponentConfigurationEndpoints(api.Group("/configs")) - signal.RegisterSignalEndpoints(api.Group("/signals")) - dashboard.RegisterDashboardEndpoints(api.Group("/dashboards")) - widget.RegisterWidgetEndpoints(api.Group("/widgets")) - file.RegisterFileEndpoints(api.Group("/files")) - user.RegisterUserEndpoints(api.Group("/users")) - infrastructure_component.RegisterICEndpoints(api.Group("/ic")) - - router.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) - -} - func addData(router *gin.Engine, mode string, basePath string) error { if mode == "test" { // test mode: drop all tables and add test data to DB database.DropTables() - log.Println("Database tables dropped, adding test data to DB") - err := database.DBAddTestData(basePath, router) + log.Println("Database tables dropped, using API to add test data") + resp, err := routes.AddTestData(basePath, router) if err != nil { - fmt.Println(err.Error()) - fmt.Println("error: testdata could not be added to DB, aborting") + fmt.Println("error: testdata could not be added to DB:", err.Error(), "Response body: ", resp) return err } - log.Println("Database initialized with test data") } else { // release mode: make sure that at least one admin user exists in DB - err := database.DBAddAdminUser() + err := helper.DBAddAdminUser() if err != nil { - fmt.Println(err.Error()) - fmt.Println("error: adding admin user failed, aborting") + fmt.Println("error: adding admin user failed:", err.Error()) return err } } return nil } -func connectAMQP(AMQPurl string, api *gin.RouterGroup) error { - if AMQPurl != "" { - log.Println("Starting AMQP client") - - err := amqp.ConnectAMQP(AMQPurl) - if err != nil { - return err - } - - // register IC action endpoint only if AMQP client is used - amqp.RegisterAMQPEndpoint(api.Group("/ic")) - - // Periodically call the Ping function to check which ICs are still there - ticker := time.NewTicker(10 * time.Second) - go func() { - - for { - select { - case <-ticker.C: - err = amqp.PingAMQP() - if err != nil { - log.Println("AMQP Error: ", err.Error()) - } - } - } - - }() - - log.Printf("Connected AMQP client to %s", AMQPurl) - } - - return nil -} - // @title VILLASweb Backend API // @version 2.0 // @description This is the VILLASweb Backend API v2.0. @@ -193,25 +68,40 @@ func connectAMQP(AMQPurl string, api *gin.RouterGroup) error { func main() { log.Println("Starting VILLASweb-backend-go") - mode, _, basePath, port, amqphost, amqpuser, amqppass, err := configureBackend() + mode, baseHost, basePath, port, amqphost, amqpuser, amqppass, err := configuration.ConfigureBackend() if err != nil { panic(err) } + + //init database + err = database.InitDB(configuration.GolbalConfig) + if err != nil { + log.Printf("Error during initialization of database: %v, aborting.", err.Error()) + panic(err) + } defer database.DBpool.Close() + // init endpoints + if mode == "release" { + gin.SetMode(gin.ReleaseMode) + } r := gin.Default() api := r.Group(basePath) - registerEndpoints(r, api) + routes.RegisterEndpoints(r, api) + apidocs.SwaggerInfo.Host = baseHost + apidocs.SwaggerInfo.BasePath = basePath + // add data to DB (if any) err = addData(r, mode, basePath) if err != nil { panic(err) } + //Start AMQP client if amqphost != "" { // create amqp URL based on username, password and host amqpurl := "amqp://" + amqpuser + ":" + amqppass + "@" + amqphost - err = connectAMQP(amqpurl, api) + err = amqp.StartAMQP(amqpurl, api) if err != nil { panic(err) }