From d2c94d188610c95b9d91353b9e9c8056b20e6a01 Mon Sep 17 00:00:00 2001 From: Sonja Happ Date: Fri, 13 Mar 2020 17:16:12 +0100 Subject: [PATCH] - models: remove imageHeight and imageWidth from File model (is customProperty of image widget) - test data: add test data in test mode via API instead of GORM - fix typos and update API documentation --- database/database.go | 17 -- database/models.go | 4 - database/testdata.go | 356 +++++++++++++++++++++++------------- doc/api/docs.go | 10 +- doc/api/swagger.json | 8 - doc/api/swagger.yaml | 6 - helper/test_utilities.go | 2 +- routes/file/file_methods.go | 2 - start.go | 28 +++ 9 files changed, 258 insertions(+), 175 deletions(-) diff --git a/database/database.go b/database/database.go index 4174f57..c271d48 100644 --- a/database/database.go +++ b/database/database.go @@ -58,10 +58,6 @@ func InitDB(cfg *config.Config) (*gorm.DB, error) { if err != nil { return nil, err } - mode, err := cfg.String("mode") - if err != nil { - return nil, err - } dbinfo := fmt.Sprintf("host=%s sslmode=%s dbname=%s", host, sslmode, name) if user != "" && pass != "" { @@ -74,20 +70,7 @@ func InitDB(cfg *config.Config) (*gorm.DB, error) { } DBpool = db - MigrateModels(db) - - if mode == "test" { - DropTables(db) - log.Println("Database tables dropped") - - err = DBAddTestData(db) - if err != nil { - return nil, err - } - log.Println("Database initialized with test data") - } - log.Println("Database connection established") return db, nil diff --git a/database/models.go b/database/models.go index fe2cc40..5eed608 100644 --- a/database/models.go +++ b/database/models.go @@ -189,10 +189,6 @@ type File struct { Type string `json:"type"` // Size of file (in byte) Size uint `json:"size"` - // Height of image (only needed in case of image) - ImageHeight uint `json:"imageHeight"` - // Width of image (only needed in case of image) - ImageWidth uint `json:"imageWidth"` // Last modification time of file Date string `json:"date"` // ID of Component Configuration to which file belongs diff --git a/database/testdata.go b/database/testdata.go index ca32da4..a4202bf 100644 --- a/database/testdata.go +++ b/database/testdata.go @@ -22,10 +22,19 @@ 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" "github.com/jinzhu/gorm/dialects/postgres" "golang.org/x/crypto/bcrypt" + "io" + "mime/multipart" + "net/http" + "net/http/httptest" + "os" "time" ) @@ -55,6 +64,36 @@ var UserB = User{Username: "User_B", Password: string(pwB), 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(`{"name" : "DPsim simulator", "category" : "Simulator", "location" : "ACSlab", "type": "DPsim"}`) @@ -117,28 +156,28 @@ var ConfigB = ComponentConfiguration{ var OutSignalA = Signal{ Name: "outSignal_A", Direction: "out", - Index: 0, + Index: 1, Unit: "V", } var OutSignalB = Signal{ Name: "outSignal_B", Direction: "out", - Index: 1, + Index: 2, Unit: "V", } var InSignalA = Signal{ Name: "inSignal_A", Direction: "in", - Index: 0, + Index: 1, Unit: "A", } var InSignalB = Signal{ Name: "inSignal_B", Direction: "in", - Index: 1, + Index: 2, Unit: "A", } @@ -156,38 +195,30 @@ var DashboardB = Dashboard{ // Files var FileA = File{ - Name: "File_A", - Type: "text/plain", - Size: 42, - ImageHeight: 333, - ImageWidth: 111, - Date: time.Now().String(), + Name: "File_A", + Type: "text/plain", + Size: 42, + Date: time.Now().String(), } var FileB = File{ - Name: "File_B", - Type: "text/plain", - Size: 1234, - ImageHeight: 55, - ImageWidth: 22, - Date: time.Now().String(), + Name: "File_B", + Type: "text/plain", + Size: 1234, + Date: time.Now().String(), } var FileC = File{ - Name: "File_C", - Type: "text/plain", - Size: 32, - ImageHeight: 10, - ImageWidth: 10, - Date: time.Now().String(), + Name: "File_C", + Type: "text/plain", + Size: 32, + Date: time.Now().String(), } var FileD = File{ - Name: "File_D", - Type: "text/plain", - Size: 5000, - ImageHeight: 400, - ImageWidth: 800, - Date: time.Now().String(), + Name: "File_D", + Type: "text/plain", + Size: 5000, + Date: time.Now().String(), } // Widgets @@ -305,133 +336,202 @@ func DBAddAdminAndUserAndGuest(db *gorm.DB) error { } // Populates DB with test data -func DBAddTestData(db *gorm.DB) error { +func DBAddTestData(db *gorm.DB, basePath string, router *gin.Engine) error { MigrateModels(db) // Create entries of each model (data defined in testdata.go) + // add Admin user + err := DBAddAdminUser(db) + if err != nil { + return err + } - //create a copy of global test data - user0 := User0 - userA := UserA - userB := UserB - userC := UserC + // authenticate as admin + token, err := helper.AuthenticateForTest(router, basePath+"/authenticate", "POST", helper.AdminCredentials) + if err != nil { + return err + } - ICA := ICA - ICB := ICB + // 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") + } - scenarioA := ScenarioA - scenarioB := ScenarioB + // 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") + } - outSignalA := OutSignalA - outSignalB := OutSignalB - inSignalA := InSignalA - inSignalB := InSignalB + // 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") + } - fileA := FileA - fileB := FileB - fileC := FileC - fileD := FileD - + // 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") + } - // Users - err := db.Create(&user0).Error + // 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") + } - // add normal users to DB - err = db.Create(&userA).Error - err = db.Create(&userB).Error + 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") + } - // add Guest user to DB - err = db.Create(&userC).Error + // upload files - // ICs - err = db.Create(&ICA).Error - err = db.Create(&ICB).Error + // upload readme file + bodyBuf := &bytes.Buffer{} + bodyWriter := multipart.NewWriter(bodyBuf) + fileWriter, _ := bodyWriter.CreateFormFile("file", "Readme.md") + fh, _ := os.Open("README.md") + defer fh.Close() - // Scenarios - err = db.Create(&scenarioA).Error - err = db.Create(&scenarioB).Error + // io copy + _, err = io.Copy(fileWriter, fh) + contentType := bodyWriter.FormDataContentType() + bodyWriter.Close() - // Signals - err = db.Create(&inSignalA).Error - err = db.Create(&inSignalB).Error - err = db.Create(&outSignalA).Error - err = db.Create(&outSignalB).Error + // 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) - // Component Configuration - err = db.Create(&configA).Error - err = db.Create(&configB).Error + // 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() - // Dashboards - err = db.Create(&dashboardA).Error - err = db.Create(&dashboardB).Error + // io copy + _, err = io.Copy(fileWriter, fh) + contentType = bodyWriter.FormDataContentType() + bodyWriter.Close() - // Files - err = db.Create(&fileA).Error - err = db.Create(&fileB).Error - err = db.Create(&fileC).Error - err = db.Create(&fileD).Error + // 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) - // Widgets - err = db.Create(&widgetA).Error - err = db.Create(&widgetB).Error - err = db.Create(&widgetC).Error - err = db.Create(&widgetD).Error - err = db.Create(&widgetE).Error - - // Associations between models - // For `belongs to` use the model with id=1 - // For `has many` use the models with id=1 and id=2 - - // User HM Scenarios, Scenario HM Users (Many-to-Many) - err = db.Model(&scenarioA).Association("Users").Append(&userA).Error - err = db.Model(&scenarioB).Association("Users").Append(&userA).Error - err = db.Model(&scenarioB).Association("Users").Append(&userB).Error - err = db.Model(&scenarioA).Association("Users").Append(&userC).Error - err = db.Model(&scenarioA).Association("Users").Append(&user0).Error - - // Scenario HM Component Configurations - err = db.Model(&scenarioA).Association("ComponentConfigurations").Append(&configA).Error - err = db.Model(&scenarioA).Association("ComponentConfigurations").Append(&configB).Error - - // Scenario HM Dashboards - err = db.Model(&scenarioA).Association("Dashboards").Append(&dashboardA).Error - err = db.Model(&scenarioA).Association("Dashboards").Append(&dashboardB).Error - - // Dashboard HM Widget - err = db.Model(&dashboardA).Association("Widgets").Append(&widgetA).Error - err = db.Model(&dashboardA).Association("Widgets").Append(&widgetB).Error - err = db.Model(&dashboardA).Association("Widgets").Append(&widgetC).Error - err = db.Model(&dashboardA).Association("Widgets").Append(&widgetD).Error - err = db.Model(&dashboardA).Association("Widgets").Append(&widgetE).Error - - // ComponentConfiguration HM Signals - err = db.Model(&configA).Association("InputMapping").Append(&inSignalA).Error - err = db.Model(&configA).Association("InputMapping").Append(&inSignalB).Error - err = db.Model(&configA).Association("InputMapping").Append(&outSignalA).Error - err = db.Model(&configA).Association("InputMapping").Append(&outSignalB).Error - - // ComponentConfiguration HM Files - err = db.Model(&configA).Association("Files").Append(&fileC).Error - err = db.Model(&configA).Association("Files").Append(&fileD).Error - - // InfrastructureComponent HM ComponentConfigurations - err = db.Model(&ICA).Association("ComponentConfigurations").Append(&configA).Error - err = db.Model(&ICA).Association("ComponentConfigurations").Append(&configB).Error - - // Widget HM Files - err = db.Model(&widgetA).Association("Files").Append(&fileA).Error - err = db.Model(&widgetA).Association("Files").Append(&fileB).Error - - return err + return nil } diff --git a/doc/api/docs.go b/doc/api/docs.go index 11b7513..65c9efa 100644 --- a/doc/api/docs.go +++ b/doc/api/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2020-03-06 15:07:22.664243647 +0100 CET m=+0.093312600 +// 2020-03-13 17:14:16.841484501 +0100 CET m=+0.100488476 package docs @@ -3259,14 +3259,6 @@ var doc = `{ "id": { "type": "integer" }, - "imageHeight": { - "description": "Height of image (only needed in case of image)", - "type": "integer" - }, - "imageWidth": { - "description": "Width of image (only needed in case of image)", - "type": "integer" - }, "name": { "description": "Name of file", "type": "string" diff --git a/doc/api/swagger.json b/doc/api/swagger.json index f9772a2..da24ea3 100644 --- a/doc/api/swagger.json +++ b/doc/api/swagger.json @@ -3244,14 +3244,6 @@ "id": { "type": "integer" }, - "imageHeight": { - "description": "Height of image (only needed in case of image)", - "type": "integer" - }, - "imageWidth": { - "description": "Width of image (only needed in case of image)", - "type": "integer" - }, "name": { "description": "Name of file", "type": "string" diff --git a/doc/api/swagger.yaml b/doc/api/swagger.yaml index 9865bed..f3278eb 100644 --- a/doc/api/swagger.yaml +++ b/doc/api/swagger.yaml @@ -123,12 +123,6 @@ definitions: type: string id: type: integer - imageHeight: - description: Height of image (only needed in case of image) - type: integer - imageWidth: - description: Width of image (only needed in case of image) - type: integer name: description: Name of file type: string diff --git a/helper/test_utilities.go b/helper/test_utilities.go index 559f962..75940c1 100644 --- a/helper/test_utilities.go +++ b/helper/test_utilities.go @@ -213,7 +213,7 @@ func AuthenticateForTest(router *gin.Engine, url string, req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { - return "", fmt.Errorf("Faile to create new request: %v", err) + return "", fmt.Errorf("Failed to create new request: %v", err) } req.Header.Set("Content-Type", "application/json") router.ServeHTTP(w, req) diff --git a/routes/file/file_methods.go b/routes/file/file_methods.go index 5888755..1af2043 100644 --- a/routes/file/file_methods.go +++ b/routes/file/file_methods.go @@ -81,8 +81,6 @@ func (f *File) register(fileHeader *multipart.FileHeader, objectType string, obj //f.Path = filepath.Join(getFolderName(objectType, objectID), f.Name) f.Size = uint(fileHeader.Size) f.Date = time.Now().String() - f.ImageWidth = 0 // TODO: do we need this? - f.ImageHeight = 0 // TODO: do we need this? var m component_configuration.ComponentConfiguration var w widget.Widget diff --git a/start.go b/start.go index 705ecc4..fc2bc35 100644 --- a/start.go +++ b/start.go @@ -22,6 +22,7 @@ package main import ( + "fmt" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/healthz" "log" "time" @@ -124,6 +125,33 @@ func main() { r.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + // add test data to DB if test mode is activated + mode, err := configuration.GolbalConfig.String("mode") + if err != nil { + fmt.Println(err.Error()) + fmt.Println("error: mode parameter missing in global configuration, aborting") + return + } + if mode == "test" { + database.DropTables(db) + log.Println("Database tables dropped") + + basePath, err := configuration.GolbalConfig.String("base.path") + if err != nil { + fmt.Println(err.Error()) + fmt.Println("error: base.path parameter missing in global configuration, aborting") + return + } + log.Println("Adding test data to DB") + err = database.DBAddTestData(db, basePath, r) + if err != nil { + fmt.Println(err.Error()) + fmt.Println("error: testdata could not be added to DB, aborting") + panic(err) + } + log.Println("Database initialized with test data") + } + amqpurl, _ := configuration.GolbalConfig.String("amqp.url") if amqpurl != "" { log.Println("Starting AMQP client")