diff --git a/database/database_test.go b/database/database_test.go index cfbd640..e3a5c9b 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -142,6 +142,8 @@ func TestScenarioAssociations(t *testing.T) { configB := ComponentConfiguration{} dashboardA := Dashboard{} dashboardB := Dashboard{} + fileA := File{} + fileB := File{} // add scenarios to DB assert.NoError(t, DBpool.Create(&scenarioA).Error) @@ -159,6 +161,10 @@ func TestScenarioAssociations(t *testing.T) { assert.NoError(t, DBpool.Create(&dashboardA).Error) assert.NoError(t, DBpool.Create(&dashboardB).Error) + // add files to DB + assert.NoError(t, DBpool.Create(&fileA).Error) + assert.NoError(t, DBpool.Create(&fileB).Error) + // add many-to-many associations between users and scenarios // User HM Scenarios, Scenario HM Users (Many-to-Many) assert.NoError(t, DBpool.Model(&scenarioA).Association("Users").Append(&userA).Error) @@ -166,6 +172,10 @@ func TestScenarioAssociations(t *testing.T) { assert.NoError(t, DBpool.Model(&scenarioB).Association("Users").Append(&userA).Error) assert.NoError(t, DBpool.Model(&scenarioB).Association("Users").Append(&userB).Error) + // add Component Configuration has many files associations + assert.NoError(t, DBpool.Model(&scenarioA).Association("Files").Append(&fileA).Error) + assert.NoError(t, DBpool.Model(&scenarioA).Association("Files").Append(&fileB).Error) + // add scenario has many component configurations associations assert.NoError(t, DBpool.Model(&scenarioA).Association("ComponentConfigurations").Append(&configA).Error) assert.NoError(t, DBpool.Model(&scenarioA).Association("ComponentConfigurations").Append(&configB).Error) @@ -200,6 +210,14 @@ func TestScenarioAssociations(t *testing.T) { assert.Fail(t, "Scenario Associations", "Expected to have %v Dashboards. Has %v.", 2, len(dashboards)) } + + // Get files of scenario1 + var files []File + assert.NoError(t, DBpool.Model(&scenario1).Related(&files, "Files").Error) + if len(files) != 2 { + assert.Fail(t, "Scenario Associations", + "Expected to have %v Files. Has %v.", 2, len(files)) + } } func TestICAssociations(t *testing.T) { @@ -249,10 +267,6 @@ func TestComponentConfigurationAssociations(t *testing.T) { outSignalB := Signal{Direction: "out"} inSignalA := Signal{Direction: "in"} inSignalB := Signal{Direction: "in"} - fileA := File{} - fileB := File{} - fileC := File{} - fileD := File{} icA := InfrastructureComponent{} icB := InfrastructureComponent{} @@ -266,12 +280,6 @@ func TestComponentConfigurationAssociations(t *testing.T) { assert.NoError(t, DBpool.Create(&inSignalA).Error) assert.NoError(t, DBpool.Create(&inSignalB).Error) - // add files to DB - assert.NoError(t, DBpool.Create(&fileA).Error) - assert.NoError(t, DBpool.Create(&fileB).Error) - assert.NoError(t, DBpool.Create(&fileC).Error) - assert.NoError(t, DBpool.Create(&fileD).Error) - // add ICs to DB assert.NoError(t, DBpool.Create(&icA).Error) assert.NoError(t, DBpool.Create(&icB).Error) @@ -282,10 +290,6 @@ func TestComponentConfigurationAssociations(t *testing.T) { assert.NoError(t, DBpool.Model(&configA).Association("OutputMapping").Append(&outSignalA).Error) assert.NoError(t, DBpool.Model(&configA).Association("OutputMapping").Append(&outSignalB).Error) - // add Component Configuration has many files associations - assert.NoError(t, DBpool.Model(&configA).Association("Files").Append(&fileC).Error) - assert.NoError(t, DBpool.Model(&configA).Association("Files").Append(&fileD).Error) - // associate Component Configurations with IC assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configA).Error) assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error) @@ -306,13 +310,6 @@ func TestComponentConfigurationAssociations(t *testing.T) { "Expected to have %v Output Signals. Has %v.", 2, len(signals)) } - // Get files of config1 - var files []File - assert.NoError(t, DBpool.Model(&config1).Related(&files, "Files").Error) - if len(files) != 2 { - assert.Fail(t, "ComponentConfiguration Associations", - "Expected to have %v Files. Has %v.", 2, len(files)) - } } func TestDashboardAssociations(t *testing.T) { @@ -358,35 +355,13 @@ func TestWidgetAssociations(t *testing.T) { // create copies of global test data widgetA := Widget{} widgetB := Widget{} - fileA := File{} - fileB := File{} - fileC := File{} - fileD := File{} // add widgets to DB assert.NoError(t, DBpool.Create(&widgetA).Error) assert.NoError(t, DBpool.Create(&widgetB).Error) - // add files to DB - assert.NoError(t, DBpool.Create(&fileA).Error) - assert.NoError(t, DBpool.Create(&fileB).Error) - assert.NoError(t, DBpool.Create(&fileC).Error) - assert.NoError(t, DBpool.Create(&fileD).Error) - - // add widget has many files associations to DB - assert.NoError(t, DBpool.Model(&widgetA).Association("Files").Append(&fileA).Error) - assert.NoError(t, DBpool.Model(&widgetA).Association("Files").Append(&fileB).Error) - var widget1 Widget assert.NoError(t, DBpool.Find(&widget1, 1).Error, fmt.Sprintf("Find Widget with ID=1")) - - // Get files of widget - var files []File - assert.NoError(t, DBpool.Model(&widget1).Related(&files, "Files").Error) - if len(files) != 2 { - assert.Fail(t, "Widget Associations", - "Expected to have %v Files. Has %v.", 2, len(files)) - } } func TestFileAssociations(t *testing.T) { diff --git a/database/models.go b/database/models.go index bfd1844..3b47289 100644 --- a/database/models.go +++ b/database/models.go @@ -69,6 +69,8 @@ type Scenario struct { ComponentConfigurations []ComponentConfiguration `json:"-" gorm:"foreignkey:ScenarioID" ` // Dashboards that belong to the Scenario Dashboards []Dashboard `json:"-" gorm:"foreignkey:ScenarioID" ` + // Files that belong to the Scenario (for example images, models, etc.) + Files []File `json:"-" gorm:"foreignkey:ScenarioID"` } // ComponentConfiguration data model @@ -90,8 +92,6 @@ type ComponentConfiguration struct { OutputMapping []Signal `json:"-" gorm:"foreignkey:ConfigID"` // Mapping of input signals of the Component Configuration, order of signals is important InputMapping []Signal `json:"-" gorm:"foreignkey:ConfigID"` - // Files of Component Configuration (can be CIM and other ComponentConfiguration file formats) - Files []File `json:"-" gorm:"foreignkey:ConfigID"` // Currently selected FileID SelectedFileID uint `json:"selectedFileID" gorm:"default:0"` } @@ -178,8 +178,6 @@ type Widget struct { CustomProperties postgres.Jsonb `json:"customProperties"` // ID of dashboard to which widget belongs DashboardID uint `json:"dashboardID"` - // Files that belong to widget (for example images) - Files []File `json:"-" gorm:"foreignkey:WidgetID"` // IDs of signals that widget uses SignalIDs pq.Int64Array `json:"signalIDs" gorm:"type:integer[]"` } @@ -195,10 +193,8 @@ type File struct { Size uint `json:"size"` // Last modification time of file Date string `json:"date"` - // ID of Component Configuration to which file belongs - ConfigID uint `json:"configID"` - // ID of widget to which file belongs - WidgetID uint `json:"widgetID"` + // ID of Scenario to which file belongs + ScenarioID uint `json:"scenarioID"` // File itself FileData []byte `json:"-" gorm:"column:FileData"` } diff --git a/doc/api/docs.go b/doc/api/docs.go index 6a987b9..6af0f5f 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-13 17:14:16.841484501 +0100 CET m=+0.100488476 +// 2020-05-26 11:22:58.121837163 +0200 CEST m=+0.130733859 package docs @@ -751,7 +751,7 @@ var doc = `{ "tags": [ "files" ], - "summary": "Get all files of a specific component configuration or widget", + "summary": "Get all files of a specific scenario", "operationId": "getFiles", "parameters": [ { @@ -761,24 +761,17 @@ var doc = `{ "in": "header", "required": true }, - { - "type": "string", - "description": "Set to config for files of component configuration, set to widget for files of widget", - "name": "objectType", - "in": "query", - "required": true - }, { "type": "integer", - "description": "ID of either config or widget of which files are requested", - "name": "objectID", + "description": "Scenario ID", + "name": "scenarioID", "in": "query", "required": true } ], "responses": { "200": { - "description": "Files which belong to config or widget", + "description": "Files which belong to scenario", "schema": { "type": "object", "$ref": "#/definitions/docs.ResponseFiles" @@ -822,7 +815,7 @@ var doc = `{ "tags": [ "files" ], - "summary": "Add a file to a specific component config or widget", + "summary": "Add a file to a specific scenario", "operationId": "addFile", "parameters": [ { @@ -839,17 +832,10 @@ var doc = `{ "in": "formData", "required": true }, - { - "type": "string", - "description": "Set to config for files of component config, set to widget for files of widget", - "name": "objectType", - "in": "query", - "required": true - }, { "type": "integer", - "description": "ID of either config or widget of which files are requested", - "name": "objectID", + "description": "ID of scenario to which file shall be added", + "name": "scenarioID", "in": "query", "required": true } @@ -3248,10 +3234,6 @@ var doc = `{ "database.File": { "type": "object", "properties": { - "configID": { - "description": "ID of Component Configuration to which file belongs", - "type": "integer" - }, "date": { "description": "Last modification time of file", "type": "string" @@ -3263,6 +3245,10 @@ var doc = `{ "description": "Name of file", "type": "string" }, + "scenarioID": { + "description": "ID of Scenario to which file belongs", + "type": "integer" + }, "size": { "description": "Size of file (in byte)", "type": "integer" @@ -3270,16 +3256,16 @@ var doc = `{ "type": { "description": "Type of file (MIME type)", "type": "string" - }, - "widgetID": { - "description": "ID of widget to which file belongs", - "type": "integer" } } }, "database.InfrastructureComponent": { "type": "object", "properties": { + "category": { + "description": "Category of IC (simulator, gateway, database, etc.)", + "type": "string" + }, "host": { "description": "Host if the IC", "type": "string" @@ -3287,8 +3273,8 @@ var doc = `{ "id": { "type": "integer" }, - "modelType": { - "description": "Model type supported by the IC", + "name": { + "description": "Name of the IC", "type": "string" }, "properties": { @@ -3307,6 +3293,10 @@ var doc = `{ "description": "Time of last state update", "type": "string" }, + "type": { + "description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)", + "type": "string" + }, "uptime": { "description": "Uptime of the IC", "type": "integer" @@ -3659,16 +3649,20 @@ var doc = `{ "infrastructure_component.validNewIC": { "type": "object", "required": [ + "Category", "Host", + "Name", "Type", - "Properties", "UUID" ], "properties": { + "Category": { + "type": "string" + }, "Host": { "type": "string" }, - "Type": { + "Name": { "type": "string" }, "Properties": { @@ -3677,6 +3671,9 @@ var doc = `{ "State": { "type": "string" }, + "Type": { + "type": "string" + }, "UUID": { "type": "string" } @@ -3685,10 +3682,13 @@ var doc = `{ "infrastructure_component.validUpdatedIC": { "type": "object", "properties": { + "Category": { + "type": "string" + }, "Host": { "type": "string" }, - "Type": { + "Name": { "type": "string" }, "Properties": { @@ -3697,6 +3697,9 @@ var doc = `{ "State": { "type": "string" }, + "Type": { + "type": "string" + }, "UUID": { "type": "string" } diff --git a/doc/api/swagger.json b/doc/api/swagger.json index da24ea3..7901d8c 100644 --- a/doc/api/swagger.json +++ b/doc/api/swagger.json @@ -736,7 +736,7 @@ "tags": [ "files" ], - "summary": "Get all files of a specific component configuration or widget", + "summary": "Get all files of a specific scenario", "operationId": "getFiles", "parameters": [ { @@ -746,24 +746,17 @@ "in": "header", "required": true }, - { - "type": "string", - "description": "Set to config for files of component configuration, set to widget for files of widget", - "name": "objectType", - "in": "query", - "required": true - }, { "type": "integer", - "description": "ID of either config or widget of which files are requested", - "name": "objectID", + "description": "Scenario ID", + "name": "scenarioID", "in": "query", "required": true } ], "responses": { "200": { - "description": "Files which belong to config or widget", + "description": "Files which belong to scenario", "schema": { "type": "object", "$ref": "#/definitions/docs.ResponseFiles" @@ -807,7 +800,7 @@ "tags": [ "files" ], - "summary": "Add a file to a specific component config or widget", + "summary": "Add a file to a specific scenario", "operationId": "addFile", "parameters": [ { @@ -824,17 +817,10 @@ "in": "formData", "required": true }, - { - "type": "string", - "description": "Set to config for files of component config, set to widget for files of widget", - "name": "objectType", - "in": "query", - "required": true - }, { "type": "integer", - "description": "ID of either config or widget of which files are requested", - "name": "objectID", + "description": "ID of scenario to which file shall be added", + "name": "scenarioID", "in": "query", "required": true } @@ -3233,10 +3219,6 @@ "database.File": { "type": "object", "properties": { - "configID": { - "description": "ID of Component Configuration to which file belongs", - "type": "integer" - }, "date": { "description": "Last modification time of file", "type": "string" @@ -3248,6 +3230,10 @@ "description": "Name of file", "type": "string" }, + "scenarioID": { + "description": "ID of Scenario to which file belongs", + "type": "integer" + }, "size": { "description": "Size of file (in byte)", "type": "integer" @@ -3255,16 +3241,16 @@ "type": { "description": "Type of file (MIME type)", "type": "string" - }, - "widgetID": { - "description": "ID of widget to which file belongs", - "type": "integer" } } }, "database.InfrastructureComponent": { "type": "object", "properties": { + "category": { + "description": "Category of IC (simulator, gateway, database, etc.)", + "type": "string" + }, "host": { "description": "Host if the IC", "type": "string" @@ -3272,8 +3258,8 @@ "id": { "type": "integer" }, - "modelType": { - "description": "Model type supported by the IC", + "name": { + "description": "Name of the IC", "type": "string" }, "properties": { @@ -3292,6 +3278,10 @@ "description": "Time of last state update", "type": "string" }, + "type": { + "description": "Type of IC (RTDS, VILLASnode, RTDS, etc.)", + "type": "string" + }, "uptime": { "description": "Uptime of the IC", "type": "integer" @@ -3644,16 +3634,20 @@ "infrastructure_component.validNewIC": { "type": "object", "required": [ + "Category", "Host", - "Modeltype", - "Properties", + "Name", + "Type", "UUID" ], "properties": { + "Category": { + "type": "string" + }, "Host": { "type": "string" }, - "Modeltype": { + "Name": { "type": "string" }, "Properties": { @@ -3662,6 +3656,9 @@ "State": { "type": "string" }, + "Type": { + "type": "string" + }, "UUID": { "type": "string" } @@ -3670,10 +3667,13 @@ "infrastructure_component.validUpdatedIC": { "type": "object", "properties": { + "Category": { + "type": "string" + }, "Host": { "type": "string" }, - "Modeltype": { + "Name": { "type": "string" }, "Properties": { @@ -3682,6 +3682,9 @@ "State": { "type": "string" }, + "Type": { + "type": "string" + }, "UUID": { "type": "string" } diff --git a/doc/api/swagger.yaml b/doc/api/swagger.yaml index f3278eb..188eaf6 100644 --- a/doc/api/swagger.yaml +++ b/doc/api/swagger.yaml @@ -115,9 +115,6 @@ definitions: type: object database.File: properties: - configID: - description: ID of Component Configuration to which file belongs - type: integer date: description: Last modification time of file type: string @@ -126,25 +123,28 @@ definitions: name: description: Name of file type: string + scenarioID: + description: ID of Scenario to which file belongs + type: integer size: description: Size of file (in byte) type: integer type: description: Type of file (MIME type) type: string - widgetID: - description: ID of widget to which file belongs - type: integer type: object database.InfrastructureComponent: properties: + category: + description: Category of IC (simulator, gateway, database, etc.) + type: string host: description: Host if the IC type: string id: type: integer - modelType: - description: Model type supported by the IC + name: + description: Name of the IC type: string properties: description: Properties of IC as JSON string @@ -158,6 +158,9 @@ definitions: stateUpdateAt: description: Time of last state update type: string + type: + description: Type of IC (RTDS, VILLASnode, RTDS, etc.) + type: string uptime: description: Uptime of the IC type: integer @@ -398,32 +401,41 @@ definitions: type: object infrastructure_component.validNewIC: properties: + Category: + type: string Host: type: string - Modeltype: + Name: type: string Properties: type: string State: type: string + Type: + type: string UUID: type: string required: + - Category - Host - - Modeltype - - Properties + - Name + - Type - UUID type: object infrastructure_component.validUpdatedIC: properties: + Category: + type: string Host: type: string - Modeltype: + Name: type: string Properties: type: string State: type: string + Type: + type: string UUID: type: string type: object @@ -1150,22 +1162,16 @@ paths: name: Authorization required: true type: string - - description: Set to config for files of component configuration, set to widget - for files of widget + - description: Scenario ID in: query - name: objectType - required: true - type: string - - description: ID of either config or widget of which files are requested - in: query - name: objectID + name: scenarioID required: true type: integer produces: - application/json responses: "200": - description: Files which belong to config or widget + description: Files which belong to scenario schema: $ref: '#/definitions/docs.ResponseFiles' type: object @@ -1184,7 +1190,7 @@ paths: schema: $ref: '#/definitions/docs.ResponseError' type: object - summary: Get all files of a specific component configuration or widget + summary: Get all files of a specific scenario tags: - files post: @@ -1207,15 +1213,9 @@ paths: name: inputFile required: true type: file - - description: Set to config for files of component config, set to widget for - files of widget + - description: ID of scenario to which file shall be added in: query - name: objectType - required: true - type: string - - description: ID of either config or widget of which files are requested - in: query - name: objectID + name: scenarioID required: true type: integer produces: @@ -1246,7 +1246,7 @@ paths: schema: $ref: '#/definitions/docs.ResponseError' type: object - summary: Add a file to a specific component config or widget + summary: Add a file to a specific scenario tags: - files /files/{fileID}: diff --git a/routes/file/file_endpoints.go b/routes/file/file_endpoints.go index 00ec497..39488cf 100644 --- a/routes/file/file_endpoints.go +++ b/routes/file/file_endpoints.go @@ -24,14 +24,11 @@ package file import ( "fmt" "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" - "net/http" - "strconv" - + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" "github.com/gin-gonic/gin" + "net/http" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" ) func RegisterFileEndpoints(r *gin.RouterGroup) { @@ -43,57 +40,28 @@ func RegisterFileEndpoints(r *gin.RouterGroup) { } // getFiles godoc -// @Summary Get all files of a specific component configuration or widget +// @Summary Get all files of a specific scenario // @ID getFiles // @Tags files // @Produce json -// @Success 200 {object} docs.ResponseFiles "Files which belong to config or widget" +// @Success 200 {object} docs.ResponseFiles "Files which belong to scenario" // @Failure 404 {object} docs.ResponseError "Not found" // @Failure 422 {object} docs.ResponseError "Unprocessable entity" // @Failure 500 {object} docs.ResponseError "Internal server error" // @Param Authorization header string true "Authorization token" -// @Param objectType query string true "Set to config for files of component configuration, set to widget for files of widget" -// @Param objectID query int true "ID of either config or widget of which files are requested" +// @Param scenarioID query int true "Scenario ID" // @Router /files [get] func getFiles(c *gin.Context) { - var err error - objectType := c.Request.URL.Query().Get("objectType") - if objectType != "config" && objectType != "widget" { - helper.BadRequestError(c, fmt.Sprintf("Object type not supported for files: %s", objectType)) - return - } - objectID_s := c.Request.URL.Query().Get("objectID") - objectID, err := strconv.Atoi(objectID_s) - if err != nil { - helper.BadRequestError(c, fmt.Sprintf("Error on ID conversion: %s", err.Error())) - return - } - - //Check access - var ok bool - var m component_configuration.ComponentConfiguration - var w widget.Widget - if objectType == "config" { - ok, m = component_configuration.CheckPermissions(c, database.Read, "body", objectID) - } else { - ok, w = widget.CheckPermissions(c, database.Read, objectID) - } + ok, so := scenario.CheckPermissions(c, database.Read, "query", -1) if !ok { return } // get meta data of files db := database.GetDB() - var files []database.File - - if objectType == "config" { - err = db.Order("ID asc").Model(&m).Related(&files, "Files").Error - } else { - err = db.Order("ID asc").Model(&w).Related(&files, "Files").Error - } - + err := db.Order("ID asc").Model(so).Related(&files, "Files").Error if !helper.DBError(c, err) { c.JSON(http.StatusOK, gin.H{"files": files}) } @@ -101,7 +69,7 @@ func getFiles(c *gin.Context) { } // addFile godoc -// @Summary Add a file to a specific component config or widget +// @Summary Add a file to a specific scenario // @ID addFile // @Tags files // @Produce json @@ -118,36 +86,14 @@ func getFiles(c *gin.Context) { // @Failure 500 {object} docs.ResponseError "Internal server error" // @Param Authorization header string true "Authorization token" // @Param inputFile formData file true "File to be uploaded" -// @Param objectType query string true "Set to config for files of component config, set to widget for files of widget" -// @Param objectID query int true "ID of either config or widget of which files are requested" +// @Param scenarioID query int true "ID of scenario to which file shall be added" // @Router /files [post] func addFile(c *gin.Context) { - objectType := c.Request.URL.Query().Get("objectType") - if objectType != "config" && objectType != "widget" { - helper.BadRequestError(c, fmt.Sprintf("Object type not supported for files: %s", objectType)) + ok, so := scenario.CheckPermissions(c, database.Read, "query", -1) + if !ok { return } - objectID_s := c.Request.URL.Query().Get("objectID") - objectID, err := strconv.Atoi(objectID_s) - if err != nil { - helper.BadRequestError(c, fmt.Sprintf("Error on ID conversion: %s", err.Error())) - return - } - - // Check access - var ok bool - if objectType == "config" { - ok, _ = component_configuration.CheckPermissions(c, database.Update, "body", objectID) - if !ok { - return - } - } else { - ok, _ = widget.CheckPermissions(c, database.Update, objectID) - if !ok { - return - } - } // Extract file from POST request form file_header, err := c.FormFile("file") @@ -157,7 +103,7 @@ func addFile(c *gin.Context) { } var newFile File - err = newFile.register(file_header, objectType, uint(objectID)) + err = newFile.register(file_header, so.ID) if !helper.DBError(c, err) { c.JSON(http.StatusOK, gin.H{"file": newFile.File}) } diff --git a/routes/file/file_methods.go b/routes/file/file_methods.go index 60d039f..f3846c5 100644 --- a/routes/file/file_methods.go +++ b/routes/file/file_methods.go @@ -22,6 +22,7 @@ package file import ( + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" "github.com/gin-gonic/gin" "io/ioutil" "mime/multipart" @@ -31,8 +32,6 @@ import ( "time" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" ) type File struct { @@ -69,37 +68,14 @@ func (f *File) download(c *gin.Context) error { return nil } -func (f *File) register(fileHeader *multipart.FileHeader, objectType string, objectID uint) error { +func (f *File) register(fileHeader *multipart.FileHeader, scenarioID uint) error { // Obtain properties of file f.Type = fileHeader.Header.Get("Content-Type") f.Name = filepath.Base(fileHeader.Filename) - //f.Path = filepath.Join(getFolderName(objectType, objectID), f.Name) f.Size = uint(fileHeader.Size) f.Date = time.Now().String() - - var m component_configuration.ComponentConfiguration - var w widget.Widget - var err error - if objectType == "config" { - // check if config exists - err = m.ByID(objectID) - f.WidgetID = 0 - f.ConfigID = objectID - if err != nil { - return err - } - - } else { - // check if widget exists - f.WidgetID = objectID - f.ConfigID = 0 - err = w.ByID(uint(objectID)) - if err != nil { - return err - } - - } + f.ScenarioID = scenarioID // set file data fileContent, err := fileHeader.Open() @@ -116,22 +92,18 @@ func (f *File) register(fileHeader *multipart.FileHeader, objectType string, obj return err } - // Create association to config or widget - if objectType == "config" { - db := database.GetDB() - err := db.Model(&m).Association("Files").Append(f).Error - if err != nil { - return err - } - } else { - db := database.GetDB() - err := db.Model(&w).Association("Files").Append(f).Error - if err != nil { - return err - } + // Create association to scenario + db := database.GetDB() + + var so scenario.Scenario + err = so.ByID(scenarioID) + if err != nil { + return err } - return nil + err = db.Model(&so).Association("Files").Append(f).Error + + return err } func (f *File) update(fileHeader *multipart.FileHeader) error { @@ -156,32 +128,19 @@ func (f *File) delete() error { db := database.GetDB() - if f.WidgetID > 0 { - // remove association between file and widget - var w widget.Widget - err := w.ByID(f.WidgetID) - if err != nil { - return err - } - err = db.Model(&w).Association("Files").Delete(f).Error - if err != nil { - return err - } - } else { - // remove association between file and config - var m component_configuration.ComponentConfiguration - err := m.ByID(f.ConfigID) - if err != nil { - return err - } - err = db.Model(&m).Association("Files").Delete(f).Error - if err != nil { - return err - } + // remove association between file and scenario + var so scenario.Scenario + err := so.ByID(f.ScenarioID) + if err != nil { + return err + } + err = db.Model(&so).Association("Files").Delete(f).Error + if err != nil { + return err } // delete file from DB - err := db.Delete(f).Error + err = db.Delete(f).Error return err } diff --git a/routes/file/file_middleware.go b/routes/file/file_middleware.go index 4a76f71..3adf779 100644 --- a/routes/file/file_middleware.go +++ b/routes/file/file_middleware.go @@ -25,8 +25,7 @@ import ( "fmt" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" "github.com/gin-gonic/gin" ) @@ -50,16 +49,9 @@ func checkPermissions(c *gin.Context, operation database.CRUD) (bool, File) { return false, f } - if f.ConfigID > 0 { - ok, _ := component_configuration.CheckPermissions(c, operation, "body", int(f.ConfigID)) - if !ok { - return false, f - } - } else { - ok, _ := widget.CheckPermissions(c, operation, int(f.WidgetID)) - if !ok { - return false, f - } + ok, _ := scenario.CheckPermissions(c, operation, "body", int(f.ScenarioID)) + if !ok { + return false, f } return true, f diff --git a/routes/file/file_test.go b/routes/file/file_test.go index 533d9cf..881371d 100644 --- a/routes/file/file_test.go +++ b/routes/file/file_test.go @@ -27,12 +27,8 @@ import ( "git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" - "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/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/user" - "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/widget" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm/dialects/postgres" "github.com/stretchr/testify/assert" @@ -47,72 +43,18 @@ import ( var router *gin.Engine -type ConfigRequest struct { - Name string `json:"name,omitempty"` - ScenarioID uint `json:"scenarioID,omitempty"` - ICID uint `json:"icID,omitempty"` - StartParameters postgres.Jsonb `json:"startParameters,omitempty"` -} - -type ICRequest struct { - UUID string `json:"uuid,omitempty"` - Host string `json:"host,omitempty"` - Type string `json:"type,omitempty"` - Name string `json:"name,omitempty"` - Category string `json:"category,omitempty"` - State string `json:"state,omitempty"` - Properties postgres.Jsonb `json:"properties,omitempty"` -} - type ScenarioRequest struct { Name string `json:"name,omitempty"` Running bool `json:"running,omitempty"` StartParameters postgres.Jsonb `json:"startParameters,omitempty"` } -type DashboardRequest struct { - Name string `json:"name,omitempty"` - Grid int `json:"grid,omitempty"` - ScenarioID uint `json:"scenarioID,omitempty"` -} - -type WidgetRequest struct { - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Width uint `json:"width,omitempty"` - Height uint `json:"height,omitempty"` - MinWidth uint `json:"minWidth,omitempty"` - MinHeight uint `json:"minHeight,omitempty"` - X int `json:"x,omitempty"` - Y int `json:"y,omitempty"` - Z int `json:"z,omitempty"` - DashboardID uint `json:"dashboardID,omitempty"` - IsLocked bool `json:"isLocked,omitempty"` - CustomProperties postgres.Jsonb `json:"customProperties,omitempty"` -} - -func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uint, configID uint, dashboardID uint, widgetID uint) { +func addScenario() (scenarioID uint) { // authenticate as admin token, _ := helper.AuthenticateForTest(router, "/api/authenticate", "POST", helper.AdminCredentials) - // POST $newICA - newICA := ICRequest{ - 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}) - - // Read newIC's ID from the response - newICID, _ := helper.GetResponseID(resp) - // authenticate as normal user token, _ = helper.AuthenticateForTest(router, "/api/authenticate", "POST", helper.UserACredentials) @@ -123,63 +65,17 @@ func addScenarioAndICAndConfigAndDashboardAndWidget() (scenarioID uint, ICID uin Running: helper.ScenarioA.Running, StartParameters: helper.ScenarioA.StartParameters, } - _, resp, _ = helper.TestEndpoint(router, token, + _, resp, _ := helper.TestEndpoint(router, token, "/api/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) // Read newScenario's ID from the response newScenarioID, _ := helper.GetResponseID(resp) - // POST new component config - newConfig := ConfigRequest{ - Name: helper.ConfigA.Name, - ScenarioID: uint(newScenarioID), - ICID: uint(newICID), - StartParameters: helper.ConfigA.StartParameters, - } - _, resp, _ = helper.TestEndpoint(router, token, - "/api/configs", "POST", helper.KeyModels{"config": newConfig}) - - // Read newConfig's ID from the response - newConfigID, _ := helper.GetResponseID(resp) - - // POST new dashboard - newDashboard := DashboardRequest{ - Name: helper.DashboardA.Name, - Grid: helper.DashboardA.Grid, - ScenarioID: uint(newScenarioID), - } - _, resp, _ = helper.TestEndpoint(router, token, - "/api/dashboards", "POST", helper.KeyModels{"dashboard": newDashboard}) - - // Read newDashboard's ID from the response - newDashboardID, _ := helper.GetResponseID(resp) - - // POST new widget - newWidget := WidgetRequest{ - 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, - "/api/widgets", "POST", helper.KeyModels{"widget": newWidget}) - - // Read newWidget's ID from the response - newWidgetID, _ := helper.GetResponseID(resp) - // add the guest user to the new scenario _, resp, _ = helper.TestEndpoint(router, token, fmt.Sprintf("/api/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) - return uint(newScenarioID), uint(newICID), uint(newConfigID), uint(newDashboardID), uint(newWidgetID) + return uint(newScenarioID) } func TestMain(m *testing.M) { @@ -198,21 +94,8 @@ func TestMain(m *testing.M) { user.RegisterAuthenticate(api.Group("/authenticate")) api.Use(user.Authentication(true)) - // component-configuration endpoints required here to first add a config to the DB - // that can be associated with a new file - component_configuration.RegisterComponentConfigurationEndpoints(api.Group("/configs")) // scenario endpoints required here to first add a scenario to the DB - // that can be associated with a new component config scenario.RegisterScenarioEndpoints(api.Group("/scenarios")) - // IC endpoints required here to first add a IC to the DB - // that can be associated with a new component config - infrastructure_component.RegisterICEndpoints(api.Group("/ic")) - // dashboard endpoints required here to first add a dashboard to the DB - // that can be associated with a new widget - dashboard.RegisterDashboardEndpoints(api.Group("/dashboards")) - // widget endpoints required here to first add a widget to the DB - // that can be associated with a new file - widget.RegisterWidgetEndpoints(api.Group("/widgets")) RegisterFileEndpoints(api.Group("/files")) @@ -226,7 +109,7 @@ func TestAddFile(t *testing.T) { // prepare the content of the DB for testing // using the respective endpoints of the API - _, _, configID, _, widgetID := addScenarioAndICAndConfigAndDashboardAndWidget() + scenarioID := addScenario() // authenticate as userB who has no access to the elements in the DB token, err := helper.AuthenticateForTest(router, @@ -235,17 +118,10 @@ func TestAddFile(t *testing.T) { emptyBuf := &bytes.Buffer{} - // try to POST to a component config to which UserB has no access + // try to POST to a scenario to which UserB has no access // should return a 422 unprocessable entity error code, resp, err := helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), "POST", emptyBuf) - assert.NoError(t, err) - assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - - // try to POST to a widget to which UserB has no access - // should return a 422 unprocessable entity error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), "POST", emptyBuf) + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "POST", emptyBuf) assert.NoError(t, err) assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) @@ -254,24 +130,17 @@ func TestAddFile(t *testing.T) { "/api/authenticate", "POST", helper.UserACredentials) assert.NoError(t, err) - // try to POST to an invalid object type + // try to POST without a scenario ID // should return a bad request error code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=wrongtype", widgetID), "POST", emptyBuf) - assert.NoError(t, err) - assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) - - // try to POST without an object ID - // should return a bad request error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectType=config"), "POST", emptyBuf) + fmt.Sprintf("/api/files"), "POST", emptyBuf) assert.NoError(t, err) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) // try to POST an invalid file // should return a bad request code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), "POST", emptyBuf) + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "POST", emptyBuf) assert.NoError(t, err) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) @@ -297,11 +166,10 @@ func TestAddFile(t *testing.T) { contentType := bodyWriter.FormDataContentType() bodyWriter.Close() - //req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf) // Create the request w := httptest.NewRecorder() - req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), bodyBuf) + req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf) assert.NoError(t, err, "create request") req.Header.Set("Content-Type", contentType) @@ -342,7 +210,7 @@ func TestUpdateFile(t *testing.T) { // prepare the content of the DB for testing // using the respective endpoints of the API - _, _, configID, _, _ := addScenarioAndICAndConfigAndDashboardAndWidget() + scenarioID := addScenario() // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -370,11 +238,10 @@ func TestUpdateFile(t *testing.T) { contentType := bodyWriter.FormDataContentType() bodyWriter.Close() - //req, err := http.NewRequest("POST", "/api/files?objectID=1&objectType=widget", bodyBuf) // Create the POST request w := httptest.NewRecorder() - req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), bodyBuf) + req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf) assert.NoError(t, err, "create request") req.Header.Set("Content-Type", contentType) @@ -476,7 +343,7 @@ func TestDeleteFile(t *testing.T) { // prepare the content of the DB for testing // using the respective endpoints of the API - _, _, configID, _, widgetID := addScenarioAndICAndConfigAndDashboardAndWidget() + scenarioID := addScenario() // authenticate as normal user token, err := helper.AuthenticateForTest(router, @@ -506,7 +373,7 @@ func TestDeleteFile(t *testing.T) { // Create the request w := httptest.NewRecorder() - req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), bodyBuf) + req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf) assert.NoError(t, err, "create request") req.Header.Set("Content-Type", contentType) req.Header.Add("Authorization", "Bearer "+token) @@ -516,7 +383,7 @@ func TestDeleteFile(t *testing.T) { newFileID, err := helper.GetResponseID(w.Body) assert.NoError(t, err) - // add a second file to a widget, this time to a widget + // add a second file to a scenario bodyBuf2 := &bytes.Buffer{} bodyWriter2 := multipart.NewWriter(bodyBuf2) fileWriter2, err := bodyWriter2.CreateFormFile("file", "testuploadfile.txt") @@ -529,7 +396,7 @@ func TestDeleteFile(t *testing.T) { // Create the request w2 := httptest.NewRecorder() - req2, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), bodyBuf2) + req2, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf2) assert.NoError(t, err, "create request") req2.Header.Set("Content-Type", contentType2) req2.Header.Add("Authorization", "Bearer "+token) @@ -544,28 +411,21 @@ func TestDeleteFile(t *testing.T) { "/api/authenticate", "POST", helper.UserBCredentials) assert.NoError(t, err) - // try to DELETE file of component config to which userB has no access + // try to DELETE file from scenario to which userB has no access // should return an unprocessable entity error code, resp, err := helper.TestEndpoint(router, token, fmt.Sprintf("/api/files/%v", newFileID), "DELETE", nil) assert.NoError(t, err) assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - // try to DELETE file of widget to which userB has no access - // should return an unprocessable entity error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files/%v", newFileID2), "DELETE", nil) - assert.NoError(t, err) - assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - // authenticate as normal user token, err = helper.AuthenticateForTest(router, "/api/authenticate", "POST", helper.UserACredentials) assert.NoError(t, err) - // Count the number of all files returned for component config + // Count the number of all files returned for scenario initialNumber, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), "GET", nil) + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "GET", nil) assert.NoError(t, err) // try to DELETE non-existing fileID @@ -580,20 +440,13 @@ func TestDeleteFile(t *testing.T) { "/api/authenticate", "POST", helper.GuestCredentials) assert.NoError(t, err) - // try to DELETE file of component config as guest + // try to DELETE file of scenario as guest // should return an unprocessable entity error code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/files/%v", newFileID), "DELETE", nil) assert.NoError(t, err) assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - // try to DELETE file of widget as guest - // should return an unprocessable entity error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files/%v", newFileID2), "DELETE", nil) - assert.NoError(t, err) - assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - // authenticate as normal user token, err = helper.AuthenticateForTest(router, "/api/authenticate", "POST", helper.UserACredentials) @@ -611,15 +464,15 @@ func TestDeleteFile(t *testing.T) { assert.NoError(t, err) assert.Equalf(t, 200, code, "Response body: \n%v\n", resp) - // Again count the number of all the files returned for component config + // Again count the number of all the files returned for scenario finalNumber, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", configID), "GET", nil) + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "GET", nil) assert.NoError(t, err) - assert.Equal(t, initialNumber-1, finalNumber) + assert.Equal(t, initialNumber-2, finalNumber) } -func TestGetAllFilesOfConfig(t *testing.T) { +func TestGetAllFilesOfScenario(t *testing.T) { database.DropTables() database.MigrateModels() @@ -627,24 +480,17 @@ func TestGetAllFilesOfConfig(t *testing.T) { // prepare the content of the DB for testing // using the respective endpoints of the API - _, _, ConfigID, _, widgetID := addScenarioAndICAndConfigAndDashboardAndWidget() + scenarioID := addScenario() // authenticate as userB who has no access to the elements in the DB token, err := helper.AuthenticateForTest(router, "/api/authenticate", "POST", helper.UserBCredentials) assert.NoError(t, err) - // try to get all files for component config to which userB has not access + // try to get all files for scenario to which userB has not access // should return unprocessable entity error code, resp, err := helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", ConfigID), "GET", nil) - assert.NoError(t, err) - assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) - - // try to get all files for widget to which userB has not access - // should return unprocessable entity error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), "GET", nil) + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "GET", nil) assert.NoError(t, err) assert.Equalf(t, 422, code, "Response body: \n%v\n", resp) @@ -653,26 +499,15 @@ func TestGetAllFilesOfConfig(t *testing.T) { "/api/authenticate", "POST", helper.UserACredentials) assert.NoError(t, err) - //try to get all files for unsupported object type; should return a bad request error + //try to get all files with missing scenario ID; should return a bad request error code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=wrongtype", ConfigID), "GET", nil) + fmt.Sprintf("/api/files"), "GET", nil) assert.NoError(t, err) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) - //try to get all files with missing object ID; should return a bad request error - code, resp, err = helper.TestEndpoint(router, token, - fmt.Sprintf("/api/files?objectType=config"), "GET", nil) - assert.NoError(t, err) - assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) - - // Count the number of all files returned for component config - initialNumberConfig, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", ConfigID), "GET", nil) - assert.NoError(t, err) - - // Count the number of all files returned for widget - initialNumberWidget, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), "GET", nil) + // Count the number of all files returned for scenario + initialNumber, err := helper.LengthOfResponse(router, token, + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "GET", nil) assert.NoError(t, err) // create a testfile.txt in local folder @@ -685,94 +520,55 @@ func TestGetAllFilesOfConfig(t *testing.T) { assert.NoError(t, err, "opening file") defer fh.Close() - // test POST a file to component config and widget - bodyBufConfig1 := &bytes.Buffer{} - bodyBufWidget1 := &bytes.Buffer{} - bodyWriterConfig1 := multipart.NewWriter(bodyBufConfig1) - bodyWriterWidget1 := multipart.NewWriter(bodyBufWidget1) - fileWriterConfig1, err := bodyWriterConfig1.CreateFormFile("file", "testuploadfile.txt") - assert.NoError(t, err, "writing to buffer") - fileWriterWidget1, err := bodyWriterWidget1.CreateFormFile("file", "testuploadfile.txt") + // test POST a file to scenario + bodyBuf1 := &bytes.Buffer{} + bodyWriter1 := multipart.NewWriter(bodyBuf1) + fileWriter1, err := bodyWriter1.CreateFormFile("file", "testuploadfile.txt") assert.NoError(t, err, "writing to buffer") // io copy - _, err = io.Copy(fileWriterConfig1, fh) + _, err = io.Copy(fileWriter1, fh) assert.NoError(t, err, "IO copy") - _, err = io.Copy(fileWriterWidget1, fh) - assert.NoError(t, err, "IO copy") - contentTypeConfig1 := bodyWriterConfig1.FormDataContentType() - contentTypeWidget1 := bodyWriterWidget1.FormDataContentType() - bodyWriterConfig1.Close() - bodyWriterWidget1.Close() + contentType1 := bodyWriter1.FormDataContentType() + bodyWriter1.Close() - // Create the request for component config + // Create the request w := httptest.NewRecorder() - req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=config", ConfigID), bodyBufConfig1) + req, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf1) assert.NoError(t, err, "create request") - req.Header.Set("Content-Type", contentTypeConfig1) + req.Header.Set("Content-Type", contentType1) req.Header.Add("Authorization", "Bearer "+token) router.ServeHTTP(w, req) assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body) - // Create the request for widget - w2 := httptest.NewRecorder() - req2, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), bodyBufWidget1) - assert.NoError(t, err, "create request") - req2.Header.Set("Content-Type", contentTypeWidget1) - req2.Header.Add("Authorization", "Bearer "+token) - router.ServeHTTP(w2, req2) - assert.Equalf(t, 200, w2.Code, "Response body: \n%v\n", w2.Body) - - // POST a second file to component config and widget + // POST a second file to scenario // open a second file handle fh2, err := os.Open("testfile.txt") assert.NoError(t, err, "opening file") defer fh2.Close() - bodyBufConfig2 := &bytes.Buffer{} - bodyBufWidget2 := &bytes.Buffer{} - bodyWriterConfig2 := multipart.NewWriter(bodyBufConfig2) - bodyWriterWidget2 := multipart.NewWriter(bodyBufWidget2) - fileWriterConfig2, err := bodyWriterConfig2.CreateFormFile("file", "testuploadfile2.txt") - assert.NoError(t, err, "writing to buffer") - fileWriterWidget2, err := bodyWriterWidget2.CreateFormFile("file", "testuploadfile2.txt") + bodyBuf2 := &bytes.Buffer{} + bodyWriter2 := multipart.NewWriter(bodyBuf2) + fileWriter2, err := bodyWriter2.CreateFormFile("file", "testuploadfile2.txt") assert.NoError(t, err, "writing to buffer") // io copy - _, err = io.Copy(fileWriterConfig2, fh2) + _, err = io.Copy(fileWriter2, fh2) assert.NoError(t, err, "IO copy") - _, err = io.Copy(fileWriterWidget2, fh2) - assert.NoError(t, err, "IO copy") - contentTypeConfig2 := bodyWriterConfig2.FormDataContentType() - contentTypeWidget2 := bodyWriterWidget2.FormDataContentType() - bodyWriterConfig2.Close() - bodyWriterWidget2.Close() + contentType2 := bodyWriter2.FormDataContentType() + bodyWriter2.Close() - w3 := httptest.NewRecorder() - req3, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=config", ConfigID), bodyBufConfig2) + w2 := httptest.NewRecorder() + req2, err := http.NewRequest("POST", fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), bodyBuf2) assert.NoError(t, err, "create request") - req3.Header.Set("Content-Type", contentTypeConfig2) - req3.Header.Add("Authorization", "Bearer "+token) - router.ServeHTTP(w3, req3) - assert.Equalf(t, 200, w3.Code, "Response body: \n%v\n", w3.Body) + req2.Header.Set("Content-Type", contentType2) + req2.Header.Add("Authorization", "Bearer "+token) + router.ServeHTTP(w2, req2) + assert.Equalf(t, 200, w2.Code, "Response body: \n%v\n", w2.Body) - w4 := httptest.NewRecorder() - req4, err := http.NewRequest("POST", fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), bodyBufWidget2) - assert.NoError(t, err, "create request") - req4.Header.Set("Content-Type", contentTypeWidget2) - req4.Header.Add("Authorization", "Bearer "+token) - router.ServeHTTP(w4, req4) - assert.Equalf(t, 200, w4.Code, "Response body: \n%v\n", w4.Body) - - // Again count the number of all the files returned for component config - finalNumberConfig, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=config", ConfigID), "GET", nil) + // Again count the number of all the files returned for scenario + finalNumber, err := helper.LengthOfResponse(router, token, + fmt.Sprintf("/api/files?scenarioID=%v", scenarioID), "GET", nil) assert.NoError(t, err) - assert.Equal(t, initialNumberConfig+2, finalNumberConfig) - - // Again count the number of all the files returned for widget - finalNumberWidget, err := helper.LengthOfResponse(router, token, - fmt.Sprintf("/api/files?objectID=%v&objectType=widget", widgetID), "GET", nil) - assert.NoError(t, err) - assert.Equal(t, initialNumberWidget+2, finalNumberWidget) + assert.Equal(t, initialNumber+2, finalNumber) } diff --git a/routes/register.go b/routes/register.go index 9cb8e75..4cc5983 100644 --- a/routes/register.go +++ b/routes/register.go @@ -264,9 +264,9 @@ func AddTestData(basePath string, router *gin.Engine) (*bytes.Buffer, error) { contentType := bodyWriter.FormDataContentType() bodyWriter.Close() - // Create the request and add file to component config + // Create the request and add file to scenario w1 := httptest.NewRecorder() - req1, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=config", bodyBuf) + req1, _ := http.NewRequest("POST", basePath+"/files?scenarioID=1", bodyBuf) req1.Header.Set("Content-Type", contentType) req1.Header.Add("Authorization", "Bearer "+token) router.ServeHTTP(w1, req1) @@ -283,9 +283,9 @@ func AddTestData(basePath string, router *gin.Engine) (*bytes.Buffer, error) { contentType = bodyWriter.FormDataContentType() bodyWriter.Close() - // Create the request and add file to widget + // Create the request and add a second file to scenario w2 := httptest.NewRecorder() - req2, _ := http.NewRequest("POST", basePath+"/files?objectID=1&objectType=widget", bodyBuf) + req2, _ := http.NewRequest("POST", basePath+"/files?scenarioID=1", bodyBuf) req2.Header.Set("Content-Type", contentType) req2.Header.Add("Authorization", "Bearer "+token) router.ServeHTTP(w2, req2)