fix linting errors found by staticcheck

This commit is contained in:
Steffen Vogel 2021-10-19 13:28:41 +02:00
parent 07c3fc9144
commit 2a9b2d4026
34 changed files with 376 additions and 290 deletions

View file

@ -121,25 +121,25 @@ func InitConfig() error {
"k8sCluster": *k8sCluster, "k8sCluster": *k8sCluster,
} }
if *dbClear == true { if *dbClear {
static["db.clear"] = "true" static["db.clear"] = "true"
} else { } else {
static["db.clear"] = "false" static["db.clear"] = "false"
} }
if *s3NoSSL == true { if *s3NoSSL {
static["s3.nossl"] = "true" static["s3.nossl"] = "true"
} else { } else {
static["s3.nossl"] = "false" static["s3.nossl"] = "false"
} }
if *s3PathStyle == true { if *s3PathStyle {
static["s3.pathstyle"] = "true" static["s3.pathstyle"] = "true"
} else { } else {
static["s3.pathstyle"] = "false" static["s3.pathstyle"] = "false"
} }
if *authExternal == true { if *authExternal {
static["auth.external.enabled"] = "true" static["auth.external.enabled"] = "true"
} else { } else {
static["auth.external.enabled"] = "false" static["auth.external.enabled"] = "false"

View file

@ -23,12 +23,13 @@ package database
import ( import (
"fmt" "fmt"
"golang.org/x/crypto/bcrypt"
"log" "log"
"math/rand" "math/rand"
"strings" "strings"
"time" "time"
"golang.org/x/crypto/bcrypt"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
"github.com/zpatrick/go-config" "github.com/zpatrick/go-config"
@ -120,12 +121,15 @@ func MigrateModels() {
} }
// DBAddAdminUser adds a default admin user to the DB // DBAddAdminUser adds a default admin user to the DB
func DBAddAdminUser(cfg *config.Config) (error, string) { func DBAddAdminUser(cfg *config.Config) (string, error) {
DBpool.AutoMigrate(User{}) DBpool.AutoMigrate(User{})
// Check if admin user exists in DB // Check if admin user exists in DB
var users []User var users []User
err := DBpool.Where("Role = ?", "Admin").Find(&users).Error err := DBpool.Where("Role = ?", "Admin").Find(&users).Error
if err != nil {
return "", err
}
adminPW := "" adminPW := ""
adminName := "" adminName := ""
@ -157,10 +161,10 @@ func DBAddAdminUser(cfg *config.Config) (error, string) {
// add admin user to DB // add admin user to DB
err = DBpool.Create(&user).Error err = DBpool.Create(&user).Error
if err != nil { if err != nil {
return err, "" return "", err
} }
} }
return nil, adminPW return adminPW, nil
} }
func generatePassword(Len int) string { func generatePassword(Len int) string {

View file

@ -22,7 +22,6 @@
package database package database
import ( import (
"fmt"
"os" "os"
"testing" "testing"
@ -68,12 +67,14 @@ func TestInitDB(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
dbuser, err := configuration.GlobalConfig.String("db.user") dbuser, err := configuration.GlobalConfig.String("db.user")
assert.NoError(t, err)
static["db.user"] = dbuser static["db.user"] = dbuser
ownconfig = config.NewConfig([]config.Provider{defaults, env}) ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig, "true") err = InitDB(ownconfig, "true")
assert.Error(t, err) assert.Error(t, err)
dbpass, err := configuration.GlobalConfig.String("db.pass") dbpass, err := configuration.GlobalConfig.String("db.pass")
assert.NoError(t, err)
static["db.pass"] = dbpass static["db.pass"] = dbpass
ownconfig = config.NewConfig([]config.Provider{defaults, env}) ownconfig = config.NewConfig([]config.Provider{defaults, env})
err = InitDB(ownconfig, "true") err = InitDB(ownconfig, "true")
@ -118,7 +119,7 @@ func TestUserAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioA).Error) assert.NoError(t, DBpool.Model(&userB).Association("Scenarios").Append(&scenarioA).Error)
var usr1 User var usr1 User
assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 1).Error, fmt.Sprintf("Find User with ID=1")) assert.NoError(t, DBpool.Find(&usr1, "ID = ?", 1).Error, "Find User with ID=1")
// Get scenarios of usr1 // Get scenarios of usr1
var scenarios []Scenario var scenarios []Scenario
@ -196,7 +197,7 @@ func TestScenarioAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&scenarioA).Association("Results").Append(&resultB).Error) assert.NoError(t, DBpool.Model(&scenarioA).Association("Results").Append(&resultB).Error)
var scenario1 Scenario var scenario1 Scenario
assert.NoError(t, DBpool.Find(&scenario1, 1).Error, fmt.Sprintf("Find Scenario with ID=1")) assert.NoError(t, DBpool.Find(&scenario1, 1).Error, "Find Scenario with ID=1")
// Get users of scenario1 // Get users of scenario1
var users []User var users []User
@ -263,7 +264,7 @@ func TestICAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error) assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error)
var ic1 InfrastructureComponent var ic1 InfrastructureComponent
assert.NoError(t, DBpool.Find(&ic1, 1).Error, fmt.Sprintf("Find InfrastructureComponent with ID=1")) assert.NoError(t, DBpool.Find(&ic1, 1).Error, "Find InfrastructureComponent with ID=1")
// Get Component Configurations of ic1 // Get Component Configurations of ic1
var configs []ComponentConfiguration var configs []ComponentConfiguration
@ -314,7 +315,7 @@ func TestComponentConfigurationAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error) assert.NoError(t, DBpool.Model(&icA).Association("ComponentConfigurations").Append(&configB).Error)
var config1 ComponentConfiguration var config1 ComponentConfiguration
assert.NoError(t, DBpool.Find(&config1, 1).Error, fmt.Sprintf("Find ComponentConfiguration with ID=1")) assert.NoError(t, DBpool.Find(&config1, 1).Error, "Find ComponentConfiguration with ID=1")
// Check IC ID // Check IC ID
if config1.ICID != 1 { if config1.ICID != 1 {
@ -355,7 +356,7 @@ func TestDashboardAssociations(t *testing.T) {
assert.NoError(t, DBpool.Model(&dashboardA).Association("Widgets").Append(&widgetB).Error) assert.NoError(t, DBpool.Model(&dashboardA).Association("Widgets").Append(&widgetB).Error)
var dashboard1 Dashboard var dashboard1 Dashboard
assert.NoError(t, DBpool.Find(&dashboard1, 1).Error, fmt.Sprintf("Find Dashboard with ID=1")) assert.NoError(t, DBpool.Find(&dashboard1, 1).Error, "Find Dashboard with ID=1")
//Get widgets of dashboard1 //Get widgets of dashboard1
var widgets []Widget var widgets []Widget
@ -380,7 +381,7 @@ func TestWidgetAssociations(t *testing.T) {
assert.NoError(t, DBpool.Create(&widgetB).Error) assert.NoError(t, DBpool.Create(&widgetB).Error)
var widget1 Widget var widget1 Widget
assert.NoError(t, DBpool.Find(&widget1, 1).Error, fmt.Sprintf("Find Widget with ID=1")) assert.NoError(t, DBpool.Find(&widget1, 1).Error, "Find Widget with ID=1")
} }
func TestFileAssociations(t *testing.T) { func TestFileAssociations(t *testing.T) {
@ -401,5 +402,5 @@ func TestFileAssociations(t *testing.T) {
assert.NoError(t, DBpool.Create(&fileD).Error) assert.NoError(t, DBpool.Create(&fileD).Error)
var file1 File var file1 File
assert.NoError(t, DBpool.Find(&file1, 1).Error, fmt.Sprintf("Find File with ID=1")) assert.NoError(t, DBpool.Find(&file1, 1).Error, "Find File with ID=1")
} }

View file

@ -66,10 +66,11 @@ type RoleActions map[string]ModelActions
// Predefined CRUD operations permissions to be used in Roles // Predefined CRUD operations permissions to be used in Roles
var crud = Permission{Create: true, Read: true, Update: true, Delete: true} var crud = Permission{Create: true, Read: true, Update: true, Delete: true}
var _ru_ = Permission{Create: false, Read: true, Update: true, Delete: false} var _ru_ = Permission{Create: false, Read: true, Update: true, Delete: false}
var __u_ = Permission{Create: false, Read: false, Update: true, Delete: false}
var _r__ = Permission{Create: false, Read: true, Update: false, Delete: false} var _r__ = Permission{Create: false, Read: true, Update: false, Delete: false}
var none = Permission{Create: false, Read: false, Update: false, Delete: false} var none = Permission{Create: false, Read: false, Update: false, Delete: false}
// var __u_ = Permission{Create: false, Read: false, Update: true, Delete: false}
// Roles is used as a look up variable to determine if a certain user is // Roles is used as a look up variable to determine if a certain user is
// allowed to do a certain action on a given model based on his role // allowed to do a certain action on a given model based on his role
var Roles = RoleActions{ var Roles = RoleActions{
@ -135,12 +136,12 @@ func ValidateRole(c *gin.Context, model ModelName, action CRUD) error {
// Get user's role from context // Get user's role from context
role, exists := c.Get(UserRoleCtx) role, exists := c.Get(UserRoleCtx)
if !exists { if !exists {
return fmt.Errorf("Request does not contain user's role") return fmt.Errorf("request does not contain user's role")
} }
// Check if the role can execute the action on the model // Check if the role can execute the action on the model
if !Roles[role.(string)][model][action] { if !Roles[role.(string)][model][action] {
return fmt.Errorf("Action not allowed for role %v", role) return fmt.Errorf("action not allowed for role %v", role)
} }
return nil return nil

View file

@ -21,6 +21,8 @@
*********************************************************************************/ *********************************************************************************/
package api package api
//lint:file-ignore U1000 Ignore all unused code, it's generated
import "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" import "git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
// This file defines the responses to any endpoint in the backend // This file defines the responses to any endpoint in the backend

View file

@ -209,8 +209,11 @@ func SendActionAMQP(action Action, destinationUUID string) error {
false, false,
false, false,
msg) msg)
return PublishAMQP(msg) if err != nil {
return err
}
return PublishAMQP(msg)
} }
func PublishAMQP(msg amqp.Publishing) error { func PublishAMQP(msg amqp.Publishing) error {

View file

@ -25,13 +25,14 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"net/http"
"net/http/httptest"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/nsf/jsondiff" "github.com/nsf/jsondiff"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"log"
"net/http"
"net/http/httptest"
) )
// data type used in testing // data type used in testing
@ -73,8 +74,8 @@ type UserRequest struct {
} }
type Credentials struct { type Credentials struct {
Username string `json:"username,required"` Username string `json:"username"`
Password string `json:"password,required"` Password string `json:"password"`
} }
var AdminCredentials = Credentials{ var AdminCredentials = Credentials{
@ -105,13 +106,13 @@ var GuestCredentials = Credentials{
func GetResponseID(resp *bytes.Buffer) (int, error) { func GetResponseID(resp *bytes.Buffer) (int, error) {
// Transform bytes buffer into byte slice // Transform bytes buffer into byte slice
respBytes := []byte(resp.String()) respBytes := resp.Bytes()
// Map JSON response to a map[string]map[string]interface{} // Map JSON response to a map[string]map[string]interface{}
var respRemapped map[string]map[string]interface{} var respRemapped map[string]map[string]interface{}
err := json.Unmarshal(respBytes, &respRemapped) err := json.Unmarshal(respBytes, &respRemapped)
if err != nil { if err != nil {
return 0, fmt.Errorf("Unmarshal failed for respRemapped %v", err) return 0, fmt.Errorf("failed to unmarshal for respRemapped %v", err)
} }
// Get an arbitrary key from tha map. The only key (entry) of // Get an arbitrary key from tha map. The only key (entry) of
@ -124,11 +125,11 @@ func GetResponseID(resp *bytes.Buffer) (int, error) {
// the conversion to integer before returning // the conversion to integer before returning
id, ok := respRemapped[arbitrary_key]["id"].(float64) id, ok := respRemapped[arbitrary_key]["id"].(float64)
if !ok { if !ok {
return 0, fmt.Errorf("Cannot type assert respRemapped") return 0, fmt.Errorf("cannot type assert respRemapped")
} }
return int(id), nil return int(id), nil
} }
return 0, fmt.Errorf("GetResponse reached exit") return 0, fmt.Errorf("getResponse reached exit")
} }
// Return the length of an response in case it is an array // Return the length of an response in case it is an array
@ -139,7 +140,7 @@ func LengthOfResponse(router *gin.Engine, token string, url string,
req, err := http.NewRequest(method, url, nil) req, err := http.NewRequest(method, url, nil)
if err != nil { if err != nil {
return 0, fmt.Errorf("Failed to create new request: %v", err) return 0, fmt.Errorf("failed to create new request: %v", err)
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer "+token) req.Header.Add("Authorization", "Bearer "+token)
@ -152,7 +153,7 @@ func LengthOfResponse(router *gin.Engine, token string, url string,
} }
// Convert the response in array of bytes // Convert the response in array of bytes
responseBytes := []byte(w.Body.String()) responseBytes := w.Body.Bytes()
// First we are trying to unmarshal the response into an array of // First we are trying to unmarshal the response into an array of
// general type variables ([]interface{}). If this fails we will try // general type variables ([]interface{}). If this fails we will try
@ -180,7 +181,7 @@ func LengthOfResponse(router *gin.Engine, token string, url string,
} }
// Failed to identify response. // Failed to identify response.
return 0, fmt.Errorf("Length of response cannot be detected") return 0, fmt.Errorf("length of response cannot be detected")
} }
// Make a request to an endpoint // Make a request to an endpoint
@ -192,13 +193,13 @@ func TestEndpoint(router *gin.Engine, token string, url string,
// Marshal the HTTP request body // Marshal the HTTP request body
body, err := json.Marshal(requestBody) body, err := json.Marshal(requestBody)
if err != nil { if err != nil {
return 0, nil, fmt.Errorf("Failed to marshal request body: %v", err) return 0, nil, fmt.Errorf("failed to marshal request body: %v", err)
} }
// Create the request // Create the request
req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil { if err != nil {
return 0, nil, fmt.Errorf("Failed to create new request: %v", err) return 0, nil, fmt.Errorf("failed to create new request: %v", err)
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer "+token) req.Header.Add("Authorization", "Bearer "+token)
@ -251,14 +252,14 @@ func CompareResponse(resp *bytes.Buffer, expected interface{}) error {
// Serialize expected response // Serialize expected response
expectedBytes, err := json.Marshal(expected) expectedBytes, err := json.Marshal(expected)
if err != nil { if err != nil {
return fmt.Errorf("Failed to marshal expected response: %v", err) return fmt.Errorf("failed to marshal expected response: %v", err)
} }
// Compare // Compare
opts := jsondiff.DefaultConsoleOptions() opts := jsondiff.DefaultConsoleOptions()
diff, text := jsondiff.Compare(resp.Bytes(), expectedBytes, &opts) diff, text := jsondiff.Compare(resp.Bytes(), expectedBytes, &opts)
if diff.String() != "FullMatch" && diff.String() != "SupersetMatch" { if diff.String() != "FullMatch" && diff.String() != "SupersetMatch" {
log.Println(text) log.Println(text)
return fmt.Errorf("Response: Expected \"%v\". Got \"%v\".", return fmt.Errorf("response: Expected \"%v\". Got \"%v\"",
"(FullMatch OR SupersetMatch)", diff.String()) "(FullMatch OR SupersetMatch)", diff.String())
} }
@ -273,25 +274,25 @@ func AuthenticateForTest(router *gin.Engine, credentials interface{}) (string, e
// Marshal credentials // Marshal credentials
body, err := json.Marshal(credentials) body, err := json.Marshal(credentials)
if err != nil { if err != nil {
return "", fmt.Errorf("Failed to marshal credentials: %v", err) return "", fmt.Errorf("failed to marshal credentials: %v", err)
} }
req, err := http.NewRequest("POST", "/api/v2/authenticate/internal", bytes.NewBuffer(body)) req, err := http.NewRequest("POST", "/api/v2/authenticate/internal", bytes.NewBuffer(body))
if err != nil { if err != nil {
return "", fmt.Errorf("Failed to create new request: %v", err) return "", fmt.Errorf("failed to create new request: %v", err)
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req) router.ServeHTTP(w, req)
// Check that return HTTP Code is 200 (OK) // Check that return HTTP Code is 200 (OK)
if w.Code != http.StatusOK { if w.Code != http.StatusOK {
return "", fmt.Errorf("HTTP Code: Expected \"%v\". Got \"%v\".", return "", fmt.Errorf("http code: Expected \"%v\". Got \"%v\"",
http.StatusOK, w.Code) http.StatusOK, w.Code)
} }
// Get the response // Get the response
var body_data map[string]interface{} var body_data map[string]interface{}
err = json.Unmarshal([]byte(w.Body.String()), &body_data) err = json.Unmarshal(w.Body.Bytes(), &body_data)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -299,16 +300,16 @@ func AuthenticateForTest(router *gin.Engine, credentials interface{}) (string, e
// Check the response // Check the response
success, ok := body_data["success"].(bool) success, ok := body_data["success"].(bool)
if !ok { if !ok {
return "", fmt.Errorf("Type asssertion of response[\"success\"] failed") return "", fmt.Errorf("type asssertion of response[\"success\"] failed")
} }
if !success { if !success {
return "", fmt.Errorf("Authentication failed: %v", body_data["message"]) return "", fmt.Errorf("authentication failed: %v", body_data["message"])
} }
// Extract the token // Extract the token
token, ok := body_data["token"].(string) token, ok := body_data["token"].(string)
if !ok { if !ok {
return "", fmt.Errorf("Type assertion of response[\"token\"] failed") return "", fmt.Errorf("type assertion of response[\"token\"] failed")
} }
// Return the token and nil error // Return the token and nil error

View file

@ -33,14 +33,14 @@ func GetIDOfElement(c *gin.Context, elementName string, source string, providedI
if source == "path" { if source == "path" {
id, err := strconv.Atoi(c.Param(elementName)) id, err := strconv.Atoi(c.Param(elementName))
if err != nil { if err != nil {
BadRequestError(c, fmt.Sprintf("No or incorrect format of path parameter")) BadRequestError(c, "No or incorrect format of path parameter")
return -1, err return -1, err
} }
return id, nil return id, nil
} else if source == "query" { } else if source == "query" {
id, err := strconv.Atoi(c.Request.URL.Query().Get(elementName)) id, err := strconv.Atoi(c.Request.URL.Query().Get(elementName))
if err != nil { if err != nil {
BadRequestError(c, fmt.Sprintf("No or incorrect format of query parameter")) BadRequestError(c, "No or incorrect format of query parameter")
return -1, err return -1, err
} }
return id, nil return id, nil

View file

@ -22,9 +22,10 @@
package component_configuration package component_configuration
import ( import (
"log"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
"log"
) )
type ComponentConfiguration struct { type ComponentConfiguration struct {
@ -149,7 +150,7 @@ func (m *ComponentConfiguration) delete() error {
if err != nil { if err != nil {
return err return err
} }
for sig, _ := range InputMappingSignals { for sig := range InputMappingSignals {
err = db.Delete(&sig).Error err = db.Delete(&sig).Error
if err != nil { if err != nil {
return err return err
@ -162,7 +163,7 @@ func (m *ComponentConfiguration) delete() error {
if err != nil { if err != nil {
return err return err
} }
for sig, _ := range OutputMappingSignals { for sig := range OutputMappingSignals {
err = db.Delete(&sig).Error err = db.Delete(&sig).Error
if err != nil { if err != nil {
return err return err

View file

@ -93,7 +93,9 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) {
State: "idle", State: "idle",
Location: "k8s", Location: "k8s",
Description: "A signal generator for testing purposes", Description: "A signal generator for testing purposes",
StartParameterSchema: postgres.Jsonb{json.RawMessage(`{"prop1" : "a nice prop"}`)}, StartParameterSchema: postgres.Jsonb{
RawMessage: json.RawMessage(`{"prop1" : "a nice prop"}`),
},
ManagedExternally: newFalse(), ManagedExternally: newFalse(),
} }
@ -119,7 +121,9 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) {
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
Name: "Scenario1", Name: "Scenario1",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`),
},
} }
code, resp, err = helper.TestEndpoint(router, token, code, resp, err = helper.TestEndpoint(router, token,
"/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) "/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario})
@ -131,7 +135,7 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) {
newScenarioID, _ := helper.GetResponseID(resp) newScenarioID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID), uint(newICID) return uint(newScenarioID), uint(newICID)

View file

@ -89,6 +89,9 @@ func (d *Dashboard) delete() error {
// remove association between Dashboard and Scenario // remove association between Dashboard and Scenario
err = db.Model(&sim).Association("Dashboards").Delete(d).Error err = db.Model(&sim).Association("Dashboards").Delete(d).Error
if err != nil {
return err
}
// get all widgets of the dashboard // get all widgets of the dashboard
var widgets []database.Widget var widgets []database.Widget
@ -98,8 +101,11 @@ func (d *Dashboard) delete() error {
} }
// Delete widgets // Delete widgets
for widget, _ := range widgets { for widget := range widgets {
err = db.Delete(&widget).Error err = db.Delete(&widget).Error
if err != nil {
return err
}
} }
// Delete dashboard // Delete dashboard

View file

@ -62,7 +62,9 @@ func addScenario(token string) (scenarioID uint) {
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
Name: "Scenario1", Name: "Scenario1",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`),
},
} }
_, resp, err := helper.TestEndpoint(router, token, _, resp, err := helper.TestEndpoint(router, token,
"/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) "/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario})
@ -74,7 +76,7 @@ func addScenario(token string) (scenarioID uint) {
newScenarioID, _ := helper.GetResponseID(resp) newScenarioID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID) return uint(newScenarioID)

View file

@ -99,8 +99,14 @@ func (f *File) Register(fileHeader *multipart.FileHeader, scenarioID uint) error
defer fileContent.Close() defer fileContent.Close()
bucket, err := configuration.GlobalConfig.String("s3.bucket") bucket, err := configuration.GlobalConfig.String("s3.bucket")
if err != nil {
return err
}
if bucket == "" { if bucket == "" {
f.FileData, err = ioutil.ReadAll(fileContent) f.FileData, err = ioutil.ReadAll(fileContent)
if err != nil {
return err
}
f.Key = "" f.Key = ""
} else { } else {
err := f.putS3(fileContent) err := f.putS3(fileContent)
@ -161,8 +167,14 @@ func (f *File) update(fileHeader *multipart.FileHeader) error {
defer fileContent.Close() defer fileContent.Close()
bucket, err := configuration.GlobalConfig.String("s3.bucket") bucket, err := configuration.GlobalConfig.String("s3.bucket")
if err != nil {
return err
}
if bucket == "" { if bucket == "" {
f.FileData, err = ioutil.ReadAll(fileContent) f.FileData, err = ioutil.ReadAll(fileContent)
if err != nil {
return err
}
f.Key = "" f.Key = ""
} else { } else {
err := f.putS3(fileContent) err := f.putS3(fileContent)

View file

@ -58,9 +58,21 @@ func getS3Session() (*session.Session, string, error) {
func createS3Session() (*session.Session, error) { func createS3Session() (*session.Session, error) {
endpoint, err := configuration.GlobalConfig.String("s3.endpoint") endpoint, err := configuration.GlobalConfig.String("s3.endpoint")
if err != nil {
return nil, err
}
region, err := configuration.GlobalConfig.String("s3.region") region, err := configuration.GlobalConfig.String("s3.region")
if err != nil {
return nil, err
}
pathStyle, err := configuration.GlobalConfig.Bool("s3.pathstyle") pathStyle, err := configuration.GlobalConfig.Bool("s3.pathstyle")
if err != nil {
return nil, err
}
nossl, err := configuration.GlobalConfig.Bool("s3.nossl") nossl, err := configuration.GlobalConfig.Bool("s3.nossl")
if err != nil {
return nil, err
}
sess, err := session.NewSession( sess, err := session.NewSession(
&aws.Config{ &aws.Config{
@ -134,6 +146,7 @@ func (f *File) getS3Url() (string, error) {
return urlStr, nil return urlStr, nil
} }
//lint:ignore U1000 will be used later
func (f *File) deleteS3() error { func (f *File) deleteS3() error {
// The session the S3 Uploader will use // The session the S3 Uploader will use

View file

@ -53,10 +53,10 @@ type ScenarioRequest struct {
func addScenario() (scenarioID uint) { func addScenario() (scenarioID uint) {
// authenticate as admin // authenticate as admin
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials) _, _ = helper.AuthenticateForTest(router, helper.AdminCredentials)
// authenticate as normal user // authenticate as normal user
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials) token, _ := helper.AuthenticateForTest(router, helper.UserACredentials)
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
@ -70,7 +70,7 @@ func addScenario() (scenarioID uint) {
newScenarioID, _ := helper.GetResponseID(resp) newScenarioID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID) return uint(newScenarioID)
@ -129,7 +129,7 @@ func TestAddFile(t *testing.T) {
// try to POST without a scenario ID // try to POST without a scenario ID
// should return a bad request error // should return a bad request error
code, resp, err = helper.TestEndpoint(router, token, code, resp, err = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/files"), "POST", emptyBuf) "/api/v2/files", "POST", emptyBuf)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)
@ -304,6 +304,7 @@ func TestUpdateFile(t *testing.T) {
assert.Equalf(t, 200, w_updated.Code, "Response body: \n%v\n", w_updated.Body) assert.Equalf(t, 200, w_updated.Code, "Response body: \n%v\n", w_updated.Body)
newFileIDUpdated, err := helper.GetResponseID(w_updated.Body) newFileIDUpdated, err := helper.GetResponseID(w_updated.Body)
assert.NoError(t, err)
assert.Equal(t, newFileID, newFileIDUpdated) assert.Equal(t, newFileID, newFileIDUpdated)
@ -407,7 +408,7 @@ func TestDeleteFile(t *testing.T) {
// try to DELETE non-existing fileID // try to DELETE non-existing fileID
// should return not found // should return not found
code, resp, err = helper.TestEndpoint(router, token, code, resp, err = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/files/5"), "DELETE", nil) "/api/v2/files/5", "DELETE", nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp) assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
@ -473,7 +474,7 @@ func TestGetAllFilesOfScenario(t *testing.T) {
//try to get all files with missing scenario ID; 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, code, resp, err = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/files"), "GET", nil) "/api/v2/files", "GET", nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)

View file

@ -104,7 +104,7 @@ func ProcessMessage(message amqp.Delivery) error {
ICUUID := payload.Properties.UUID ICUUID := payload.Properties.UUID
_, err = uuid.Parse(ICUUID) _, err = uuid.Parse(ICUUID)
if err != nil { if err != nil {
return fmt.Errorf("AMQP: UUID not valid: %v, message ignored: %v \n", ICUUID, string(message.Body)) return fmt.Errorf("amqp: UUID not valid: %v, message ignored: %vi", ICUUID, string(message.Body))
} }
var sToBeUpdated InfrastructureComponent var sToBeUpdated InfrastructureComponent

View file

@ -25,23 +25,21 @@ package infrastructure_component
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/go-resty/resty/v2"
"github.com/jinzhu/gorm/dialects/postgres"
"log" "log"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/go-resty/resty/v2"
"github.com/jinzhu/gorm/dialects/postgres"
) )
func QueryICAPIs(d time.Duration) { func QueryICAPIs(d time.Duration) {
client := resty.New()
//client.SetDebug(true)
go func() { go func() {
for _ = range time.Tick(d) { for range time.Tick(d) {
//log.Println("Querying IC APIs at time:", x) //log.Println("Querying IC APIs at time:", x)
var err error var err error
@ -55,28 +53,49 @@ func QueryICAPIs(d time.Duration) {
// iterate over ICs in DB // iterate over ICs in DB
for _, ic := range ics { for _, ic := range ics {
err := queryIC(&ic)
if ic.ManagedExternally { if err != nil {
continue fmt.Println(err)
}
}
}
}()
} }
if ic.APIURL == "" || (!strings.HasPrefix(ic.APIURL, "http://") && !strings.HasPrefix(ic.APIURL, "https://")) { func queryIC(ic *database.InfrastructureComponent) error {
continue if ic.ManagedExternally || ic.APIURL == "" || (!strings.HasPrefix(ic.APIURL, "http://") && !strings.HasPrefix(ic.APIURL, "https://")) {
return nil
} }
if ic.Category == "gateway" && ic.Type == "villas-node" { if ic.Category == "gateway" {
if ic.Type == "villas-node" {
err := queryVillasNodeGateway(ic)
if err != nil {
return err
}
} else if ic.Type == "villas-relay" {
err := queryVillasRelayGateway(ic)
if err != nil {
return err
}
}
}
return nil
}
func queryVillasNodeGateway(ic *database.InfrastructureComponent) error {
client := resty.New()
log.Println("External API: checking for villas-node gateway", ic.Name) log.Println("External API: checking for villas-node gateway", ic.Name)
statusResponse, err := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL + "/status") statusResponse, err := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL + "/status")
if err != nil { if err != nil {
log.Println("Error querying status of", ic.Name, err) return fmt.Errorf("failed to query the status of %s: %w", ic.Name, err)
continue
} }
var status map[string]interface{} var status map[string]interface{}
err = json.Unmarshal(statusResponse.Body(), &status) err = json.Unmarshal(statusResponse.Body(), &status)
if err != nil { if err != nil {
log.Println("Error unmarshalling status of", ic.Name, err) return fmt.Errorf("failed to unmarshal status of %s: %w", ic.Name, err)
continue
} }
parts := strings.Split(ic.WebsocketURL, "/") parts := strings.Split(ic.WebsocketURL, "/")
@ -102,15 +121,13 @@ func QueryICAPIs(d time.Duration) {
updatedIC.InfrastructureComponent.StatusUpdateRaw = postgres.Jsonb{RawMessage: statusRaw} updatedIC.InfrastructureComponent.StatusUpdateRaw = postgres.Jsonb{RawMessage: statusRaw}
updatedIC.InfrastructureComponent.State = fmt.Sprintf("%v", status["state"]) updatedIC.InfrastructureComponent.State = fmt.Sprintf("%v", status["state"])
updatedIC.InfrastructureComponent.UUID = fmt.Sprintf("%v", status["uuid"]) updatedIC.InfrastructureComponent.UUID = fmt.Sprintf("%v", status["uuid"])
timeNow, myerr := strconv.ParseFloat(fmt.Sprintf("%v", status["time_now"]), 64) timeNow, err := strconv.ParseFloat(fmt.Sprintf("%v", status["time_now"]), 64)
if myerr != nil { if err != nil {
log.Println("Error parsing time_now to float", myerr.Error()) return fmt.Errorf("failed to parse time_now to float: %w", err)
continue
} }
timeStarted, myerr := strconv.ParseFloat(fmt.Sprintf("%v", status["time_started"]), 64) timeStarted, err := strconv.ParseFloat(fmt.Sprintf("%v", status["time_started"]), 64)
if myerr != nil { if err != nil {
log.Println("Error parsing time_started to float", myerr.Error()) return fmt.Errorf("failed to parse time_started to float: %w", err)
continue
} }
uptime := timeNow - timeStarted uptime := timeNow - timeStarted
updatedIC.InfrastructureComponent.Uptime = uptime updatedIC.InfrastructureComponent.Uptime = uptime
@ -118,37 +135,37 @@ func QueryICAPIs(d time.Duration) {
// validate the update // validate the update
err = updatedIC.validate() err = updatedIC.validate()
if err != nil { if err != nil {
log.Println("Error validating updated villas-node gateway", ic.Name, ic.UUID, err.Error()) return fmt.Errorf("failed to validate updated villas-node gateway: %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
// create the update and update IC in DB // create the update and update IC in DB
var x InfrastructureComponent var x InfrastructureComponent
err = x.byID(ic.ID) err = x.byID(ic.ID)
if err != nil { if err != nil {
log.Println("Error getting villas-node gateway by ID", ic.Name, err) return fmt.Errorf("failed to get villas-node gateway by ID %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
u := updatedIC.updatedIC(x) u := updatedIC.updatedIC(x)
err = x.update(u) err = x.update(u)
if err != nil { if err != nil {
log.Println("Error updating villas-node gateway", ic.Name, ic.UUID, err.Error()) return fmt.Errorf("failed to update villas-node gateway %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
} else if ic.Category == "manager" && ic.Type == "villas-relay" { return nil
}
func queryVillasRelayGateway(ic *database.InfrastructureComponent) error {
client := resty.New()
log.Println("External API: checking for villas-relay manager", ic.Name) log.Println("External API: checking for villas-relay manager", ic.Name)
statusResponse, err := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL) statusResponse, err := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL)
if err != nil { if err != nil {
log.Println("Error querying API of", ic.Name, err) return fmt.Errorf("failed querying API of %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
var status map[string]interface{} var status map[string]interface{}
err = json.Unmarshal(statusResponse.Body(), &status) err = json.Unmarshal(statusResponse.Body(), &status)
if err != nil { if err != nil {
log.Println("Error unmarshalling status villas-relay manager", ic.Name, err) return fmt.Errorf("failed to unmarshal status villas-relay manager %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
var updatedIC UpdateICRequest var updatedIC UpdateICRequest
@ -159,30 +176,20 @@ func QueryICAPIs(d time.Duration) {
// validate the update // validate the update
err = updatedIC.validate() err = updatedIC.validate()
if err != nil { if err != nil {
log.Println("Error validating updated villas-relay manager", ic.Name, ic.UUID, err.Error()) return fmt.Errorf("failed to validate updated villas-relay manager %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
// create the update and update IC in DB // create the update and update IC in DB
var x InfrastructureComponent var x InfrastructureComponent
err = x.byID(ic.ID) err = x.byID(ic.ID)
if err != nil { if err != nil {
log.Println("Error getting villas-relay manager by ID", ic.Name, err) return fmt.Errorf("failed to get villas-relay manager by ID %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
u := updatedIC.updatedIC(x) u := updatedIC.updatedIC(x)
err = x.update(u) err = x.update(u)
if err != nil { if err != nil {
log.Println("Error updating villas-relay manager", ic.Name, ic.UUID, err.Error()) return fmt.Errorf("failed to update villas-relay manager %s (%s): %w", ic.Name, ic.UUID, err)
continue
} }
} else if ic.Category == "gateway" && ic.Type == "villas-relay" { return nil
// TODO add code here once API for VILLASrelay sessions is available
}
}
}
}()
} }

View file

@ -102,7 +102,7 @@ func addIC(c *gin.Context) {
} }
// Check if IC to be created is managed externally // Check if IC to be created is managed externally
if *req.InfrastructureComponent.ManagedExternally == true { if *req.InfrastructureComponent.ManagedExternally {
// if so: refuse creation // if so: refuse creation
helper.BadRequestError(c, "create for externally managed IC not possible with this endpoint - use /ic/{ICID}/action endpoint instead to request creation of the component") helper.BadRequestError(c, "create for externally managed IC not possible with this endpoint - use /ic/{ICID}/action endpoint instead to request creation of the component")
return return

View file

@ -87,8 +87,8 @@ var newIC1 = ICRequest{
State: "idle", State: "idle",
Location: "k8s", Location: "k8s",
Description: "A signal generator for testing purposes", Description: "A signal generator for testing purposes",
StartParameterSchema: postgres.Jsonb{json.RawMessage(`{"startprop1" : "a nice prop"}`)}, StartParameterSchema: postgres.Jsonb{RawMessage: json.RawMessage(`{"startprop1" : "a nice prop"}`)},
CreateParameterSchema: postgres.Jsonb{json.RawMessage(`{"createprop1" : "a really nice prop"}`)}, CreateParameterSchema: postgres.Jsonb{RawMessage: json.RawMessage(`{"createprop1" : "a really nice prop"}`)},
ManagedExternally: newFalse(), ManagedExternally: newFalse(),
Manager: "7be0322d-354e-431e-84bd-ae4c9633beef", Manager: "7be0322d-354e-431e-84bd-ae4c9633beef",
} }
@ -103,8 +103,8 @@ var newIC2 = ICRequest{
State: "running", State: "running",
Location: "k8s", Location: "k8s",
Description: "This is a test description", Description: "This is a test description",
StartParameterSchema: postgres.Jsonb{json.RawMessage(`{"startprop1" : "a nice prop"}`)}, StartParameterSchema: postgres.Jsonb{RawMessage: json.RawMessage(`{"startprop1" : "a nice prop"}`)},
CreateParameterSchema: postgres.Jsonb{json.RawMessage(`{"createprop1" : "a really nice prop"}`)}, CreateParameterSchema: postgres.Jsonb{RawMessage: json.RawMessage(`{"createprop1" : "a really nice prop"}`)},
ManagedExternally: newTrue(), ManagedExternally: newTrue(),
Manager: "4854af30-325f-44a5-ad59-b67b2597de99", Manager: "4854af30-325f-44a5-ad59-b67b2597de99",
} }
@ -141,9 +141,9 @@ func TestMain(m *testing.M) {
// connect AMQP client // connect AMQP client
// Make sure that AMQP_HOST, AMQP_USER, AMQP_PASS are set // Make sure that AMQP_HOST, AMQP_USER, AMQP_PASS are set
host, err := configuration.GlobalConfig.String("amqp.host") host, _ := configuration.GlobalConfig.String("amqp.host")
usr, err := configuration.GlobalConfig.String("amqp.user") usr, _ := configuration.GlobalConfig.String("amqp.user")
pass, err := configuration.GlobalConfig.String("amqp.pass") pass, _ := configuration.GlobalConfig.String("amqp.pass")
amqpURI := "amqp://" + usr + ":" + pass + "@" + host amqpURI := "amqp://" + usr + ":" + pass + "@" + host
// AMQP Connection startup is tested here // AMQP Connection startup is tested here
@ -306,8 +306,7 @@ func TestUpdateICAsAdmin(t *testing.T) {
payload, err := json.Marshal(update) payload, err := json.Marshal(update)
assert.NoError(t, err) assert.NoError(t, err)
var headers map[string]interface{} var headers map[string]interface{} = make(map[string]interface{}) // empty map
headers = make(map[string]interface{}) // empty map
headers["uuid"] = newIC2.Manager // set uuid headers["uuid"] = newIC2.Manager // set uuid
msg := amqp.Publishing{ msg := amqp.Publishing{
@ -426,8 +425,7 @@ func TestDeleteICAsAdmin(t *testing.T) {
payload, err := json.Marshal(update) payload, err := json.Marshal(update)
assert.NoError(t, err) assert.NoError(t, err)
var headers map[string]interface{} var headers map[string]interface{} = make(map[string]interface{}) // empty map
headers = make(map[string]interface{}) // empty map
headers["uuid"] = newIC2.UUID // set uuid headers["uuid"] = newIC2.UUID // set uuid
msg := amqp.Publishing{ msg := amqp.Publishing{
@ -620,7 +618,7 @@ func TestSendActionToIC(t *testing.T) {
var params startParams var params startParams
params.UUID = newIC1.UUID params.UUID = newIC1.UUID
paramsRaw, err := json.Marshal(&params) paramsRaw, _ := json.Marshal(&params)
action1.Parameters = paramsRaw action1.Parameters = paramsRaw
actions := [1]helper.Action{action1} actions := [1]helper.Action{action1}
@ -654,8 +652,7 @@ func TestCreateUpdateViaAMQPRecv(t *testing.T) {
payload, err := json.Marshal(update) payload, err := json.Marshal(update)
assert.NoError(t, err) assert.NoError(t, err)
var headers map[string]interface{} var headers map[string]interface{} = make(map[string]interface{}) // empty map
headers = make(map[string]interface{}) // empty map
headers["uuid"] = newIC1.Manager // set uuid headers["uuid"] = newIC1.Manager // set uuid
msg := amqp.Publishing{ msg := amqp.Publishing{
@ -697,8 +694,7 @@ func TestCreateUpdateViaAMQPRecv(t *testing.T) {
payload, err = json.Marshal(update) payload, err = json.Marshal(update)
assert.NoError(t, err) assert.NoError(t, err)
var headersA map[string]interface{} var headersA map[string]interface{} = make(map[string]interface{}) // empty map
headersA = make(map[string]interface{}) // empty map
headersA["uuid"] = newIC1.Manager headersA["uuid"] = newIC1.Manager
msg = amqp.Publishing{ msg = amqp.Publishing{
@ -777,8 +773,7 @@ func TestDeleteICViaAMQPRecv(t *testing.T) {
payload, err := json.Marshal(update) payload, err := json.Marshal(update)
assert.NoError(t, err) assert.NoError(t, err)
var headers map[string]interface{} var headers map[string]interface{} = make(map[string]interface{}) // empty map
headers = make(map[string]interface{}) // empty map
headers["uuid"] = newIC1.Manager // set uuid headers["uuid"] = newIC1.Manager // set uuid
msg := amqp.Publishing{ msg := amqp.Publishing{
@ -828,7 +823,9 @@ func TestDeleteICViaAMQPRecv(t *testing.T) {
Name: "ConfigA", Name: "ConfigA",
ScenarioID: uint(newScenarioID), ScenarioID: uint(newScenarioID),
ICID: 1, ICID: 1,
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 55}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 55}`),
},
FileIDs: []int64{}, FileIDs: []int64{},
} }

View file

@ -88,7 +88,7 @@ func (r *AddICRequest) validate() error {
return errs return errs
} }
if *r.InfrastructureComponent.ManagedExternally == true { if *r.InfrastructureComponent.ManagedExternally {
// check if valid manager UUID is provided // check if valid manager UUID is provided
_, errs = uuid.Parse(r.InfrastructureComponent.Manager) _, errs = uuid.Parse(r.InfrastructureComponent.Manager)
if errs != nil { if errs != nil {
@ -119,8 +119,7 @@ func (r *UpdateICRequest) validate() error {
func (r *AddICRequest) createIC() (InfrastructureComponent, error) { func (r *AddICRequest) createIC() (InfrastructureComponent, error) {
var s InfrastructureComponent var s InfrastructureComponent
var err error var err error = nil
err = nil
s.UUID = r.InfrastructureComponent.UUID s.UUID = r.InfrastructureComponent.UUID
s.WebsocketURL = r.InfrastructureComponent.WebsocketURL s.WebsocketURL = r.InfrastructureComponent.WebsocketURL

View file

@ -311,7 +311,7 @@ func AddTestData(cfg *config.Config, router *gin.Engine) (*bytes.Buffer, error)
defer fh.Close() defer fh.Close()
// io copy // io copy
_, err = io.Copy(fileWriter, fh) _, _ = io.Copy(fileWriter, fh)
contentType := bodyWriter.FormDataContentType() contentType := bodyWriter.FormDataContentType()
bodyWriter.Close() bodyWriter.Close()
@ -338,7 +338,7 @@ func AddTestData(cfg *config.Config, router *gin.Engine) (*bytes.Buffer, error)
defer fh.Close() defer fh.Close()
// io copy // io copy
_, err = io.Copy(fileWriter, fh) _, _ = io.Copy(fileWriter, fh)
contentType := bodyWriter.FormDataContentType() contentType := bodyWriter.FormDataContentType()
bodyWriter.Close() bodyWriter.Close()

View file

@ -66,8 +66,11 @@ func TestStartAMQP(t *testing.T) {
// connect AMQP client // connect AMQP client
// Make sure that AMQP_HOST, AMQP_USER, AMQP_PASS are set // Make sure that AMQP_HOST, AMQP_USER, AMQP_PASS are set
host, err := configuration.GlobalConfig.String("amqp.host") host, err := configuration.GlobalConfig.String("amqp.host")
assert.NoError(t, err)
user, err := configuration.GlobalConfig.String("amqp.user") user, err := configuration.GlobalConfig.String("amqp.user")
assert.NoError(t, err)
pass, err := configuration.GlobalConfig.String("amqp.pass") pass, err := configuration.GlobalConfig.String("amqp.pass")
assert.NoError(t, err)
amqpURI := "amqp://" + user + ":" + pass + "@" + host amqpURI := "amqp://" + user + ":" + pass + "@" + host
// AMQP Connection startup is tested here // AMQP Connection startup is tested here

View file

@ -23,10 +23,11 @@
package result package result
import ( import (
"log"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
"log"
) )
type Result struct { type Result struct {
@ -92,6 +93,9 @@ func (r *Result) delete() error {
// remove association between Result and Scenario // remove association between Result and Scenario
err = db.Model(&sco).Association("Results").Delete(r).Error err = db.Model(&sco).Association("Results").Delete(r).Error
if err != nil {
return err
}
// Delete result files // Delete result files
for _, fileid := range r.ResultFileIDs { for _, fileid := range r.ResultFileIDs {

View file

@ -70,10 +70,10 @@ var newResult = ResultRequest{
func addScenario() (scenarioID uint) { func addScenario() (scenarioID uint) {
// authenticate as admin // authenticate as admin
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials) helper.AuthenticateForTest(router, helper.AdminCredentials)
// authenticate as normal user // authenticate as normal user
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials) token, _ := helper.AuthenticateForTest(router, helper.UserACredentials)
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
@ -87,7 +87,7 @@ func addScenario() (scenarioID uint) {
newScenarioID, _ := helper.GetResponseID(resp) newScenarioID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID) return uint(newScenarioID)
@ -135,7 +135,9 @@ func TestGetAllResultsOfScenario(t *testing.T) {
// test POST newResult // test POST newResult
configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`) configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`)
confSnapshots := postgres.Jsonb{configSnapshot1} confSnapshots := postgres.Jsonb{
RawMessage: configSnapshot1,
}
newResult.ScenarioID = scenarioID newResult.ScenarioID = scenarioID
newResult.ConfigSnapshots = confSnapshots newResult.ConfigSnapshots = confSnapshots
@ -174,7 +176,9 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
// by adding a scenario // by adding a scenario
scenarioID := addScenario() scenarioID := addScenario()
configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`) configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`)
confSnapshots := postgres.Jsonb{configSnapshot1} confSnapshots := postgres.Jsonb{
RawMessage: configSnapshot1,
}
newResult.ScenarioID = scenarioID newResult.ScenarioID = scenarioID
newResult.ConfigSnapshots = confSnapshots newResult.ConfigSnapshots = confSnapshots
// authenticate as normal userB who has no access to new scenario // authenticate as normal userB who has no access to new scenario
@ -347,7 +351,9 @@ func TestAddDeleteResultFile(t *testing.T) {
// by adding a scenario // by adding a scenario
scenarioID := addScenario() scenarioID := addScenario()
configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`) configSnapshot1 := json.RawMessage(`{"configs": [ {"Name" : "conf1", "scenarioID" : 1}, {"Name" : "conf2", "scenarioID" : 1}]}`)
confSnapshots := postgres.Jsonb{configSnapshot1} confSnapshots := postgres.Jsonb{
RawMessage: configSnapshot1,
}
newResult.ScenarioID = scenarioID newResult.ScenarioID = scenarioID
newResult.ConfigSnapshots = confSnapshots newResult.ConfigSnapshots = confSnapshots
@ -404,6 +410,7 @@ func TestAddDeleteResultFile(t *testing.T) {
assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body) assert.Equalf(t, 200, w.Code, "Response body: \n%v\n", w.Body)
err = helper.CompareResponse(w.Body, helper.KeyModels{"result": newResult}) err = helper.CompareResponse(w.Body, helper.KeyModels{"result": newResult})
assert.NoError(t, err)
// extract file ID from response body // extract file ID from response body
var respResult ResponseResult var respResult ResponseResult
@ -455,6 +462,7 @@ func TestAddDeleteResultFile(t *testing.T) {
assert.Equalf(t, 200, w2.Code, "Response body: \n%v\n", w2.Body) assert.Equalf(t, 200, w2.Code, "Response body: \n%v\n", w2.Body)
err = helper.CompareResponse(w2.Body, helper.KeyModels{"result": newResult}) err = helper.CompareResponse(w2.Body, helper.KeyModels{"result": newResult})
assert.NoError(t, err)
// extract file ID from response body // extract file ID from response body
var respResult3 ResponseResult var respResult3 ResponseResult

View file

@ -23,6 +23,7 @@ package scenario
import ( import (
"fmt" "fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
@ -105,6 +106,9 @@ func (s *Scenario) deleteUser(username string) error {
// There is only one associated user // There is only one associated user
var remainingUser user.User var remainingUser user.User
err = db.Model(s).Related(&remainingUser, "Users").Error err = db.Model(s).Related(&remainingUser, "Users").Error
if err != nil {
return err
}
if remainingUser.Username == username { if remainingUser.Username == username {
// if the remaining user is the one to be deleted // if the remaining user is the one to be deleted
return fmt.Errorf("cannot delete last user from scenario without deleting scenario itself, doing nothing") return fmt.Errorf("cannot delete last user from scenario without deleting scenario itself, doing nothing")

View file

@ -23,6 +23,7 @@ package scenario
import ( import (
"fmt" "fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -55,7 +56,7 @@ func CheckPermissions(c *gin.Context, operation database.CRUD, scenarioIDsource
return false, so return false, so
} }
if so.checkAccess(userID.(uint), operation) == false { if !so.checkAccess(userID.(uint), operation) {
helper.UnprocessableEntityError(c, "Access denied (user has no access or scenario is locked).") helper.UnprocessableEntityError(c, "Access denied (user has no access or scenario is locked).")
return false, so return false, so
} }

View file

@ -54,12 +54,16 @@ type UserRequest struct {
var newScenario1 = ScenarioRequest{ var newScenario1 = ScenarioRequest{
Name: "Scenario1", Name: "Scenario1",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`),
},
} }
var newScenario2 = ScenarioRequest{ var newScenario2 = ScenarioRequest{
Name: "Scenario2", Name: "Scenario2",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 55}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 55}`),
},
} }
func TestMain(m *testing.M) { func TestMain(m *testing.M) {

View file

@ -103,8 +103,12 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) {
State: "idle", State: "idle",
Location: "k8s", Location: "k8s",
Description: "A signal generator for testing purposes", Description: "A signal generator for testing purposes",
StartParameterSchema: postgres.Jsonb{json.RawMessage(`{"startprop1" : "a nice prop"}`)}, StartParameterSchema: postgres.Jsonb{
CreateParameterSchema: postgres.Jsonb{json.RawMessage(`{"createprop1" : "a really nice prop"}`)}, RawMessage: json.RawMessage(`{"startprop1" : "a nice prop"}`),
},
CreateParameterSchema: postgres.Jsonb{
RawMessage: json.RawMessage(`{"createprop1" : "a really nice prop"}`),
},
ManagedExternally: newFalse(), ManagedExternally: newFalse(),
} }
_, resp, _ := helper.TestEndpoint(router, token, _, resp, _ := helper.TestEndpoint(router, token,
@ -119,7 +123,9 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) {
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
Name: "Scenario1", Name: "Scenario1",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`),
},
} }
_, resp, _ = helper.TestEndpoint(router, token, _, resp, _ = helper.TestEndpoint(router, token,
"/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) "/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario})
@ -141,7 +147,7 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) {
newConfigID, _ := helper.GetResponseID(resp) newConfigID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID), uint(newICID), uint(newConfigID) return uint(newScenarioID), uint(newICID), uint(newConfigID)
@ -189,12 +195,12 @@ func TestAddSignal(t *testing.T) {
_, _, configID := addScenarioAndICAndConfig() _, _, configID := addScenarioAndICAndConfig()
// authenticate as normal user // authenticate as normal user
token, err := helper.AuthenticateForTest(router, helper.UserACredentials) _, err := helper.AuthenticateForTest(router, helper.UserACredentials)
assert.NoError(t, err) assert.NoError(t, err)
newSignal1.ConfigID = configID newSignal1.ConfigID = configID
// authenticate as normal userB who has no access to new scenario // authenticate as normal userB who has no access to new scenario
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials) token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
assert.NoError(t, err) assert.NoError(t, err)
// try to POST to component config without access // try to POST to component config without access

View file

@ -43,7 +43,7 @@ func NewUser(username, password, mail, role string, active bool) (User, error) {
// Check that the username is NOT taken // Check that the username is NOT taken
err := newUser.ByUsername(username) err := newUser.ByUsername(username)
if err == nil { if err == nil {
return newUser, fmt.Errorf("Username is already taken") return newUser, fmt.Errorf("username is already taken")
} }
newUser.Username = username newUser.Username = username
@ -97,12 +97,12 @@ func (u *User) ByID(id uint) error {
func (u *User) setPassword(password string) error { func (u *User) setPassword(password string) error {
if len(password) == 0 { if len(password) == 0 {
return fmt.Errorf("Password cannot be empty") return fmt.Errorf("password cannot be empty")
} }
newPassword, err := newPassword, err :=
bcrypt.GenerateFromPassword([]byte(password), bcryptCost) bcrypt.GenerateFromPassword([]byte(password), bcryptCost)
if err != nil { if err != nil {
return fmt.Errorf("Failed to generate hash from password") return fmt.Errorf("failed to generate hash from password")
} }
u.Password = string(newPassword) u.Password = string(newPassword)
return nil return nil

View file

@ -62,7 +62,7 @@ func isAuthenticated(c *gin.Context) (bool, error) {
func(token *jwt.Token) (interface{}, error) { func(token *jwt.Token) (interface{}, error) {
// Validate alg for signing the jwt // Validate alg for signing the jwt
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing alg: %v", return nil, fmt.Errorf("unexpected signing alg: %v",
token.Header["alg"]) token.Header["alg"])
} }

View file

@ -75,7 +75,7 @@ func TestMain(m *testing.M) {
func TestAuthenticate(t *testing.T) { func TestAuthenticate(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// try to authenticate with non JSON body // try to authenticate with non JSON body
@ -172,7 +172,7 @@ func TestAuthenticateQueryToken(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -193,7 +193,7 @@ func TestAddGetUser(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -308,7 +308,7 @@ func TestAddGetUser(t *testing.T) {
// try to GET user with invalid user ID // try to GET user with invalid user ID
// should result in bad request // should result in bad request
code, resp, err = helper.TestEndpoint(router, token, code, resp, err = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/users/bla"), "GET", nil) "/api/v2/users/bla", "GET", nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)
} }
@ -317,7 +317,7 @@ func TestUsersNotAllowedActions(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -376,7 +376,7 @@ func TestGetAllUsers(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -429,7 +429,7 @@ func TestModifyAddedUserAsUser(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -460,7 +460,7 @@ func TestModifyAddedUserAsUser(t *testing.T) {
// Try PUT with invalid user ID in path // Try PUT with invalid user ID in path
// Should return a bad request // Should return a bad request
code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/v2/users/blabla"), "PUT", code, resp, err = helper.TestEndpoint(router, token, "/api/v2/users/blabla", "PUT",
helper.KeyModels{"user": newUser}) helper.KeyModels{"user": newUser})
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)
@ -584,7 +584,7 @@ func TestInvalidUserUpdate(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -657,7 +657,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -774,7 +774,7 @@ func TestDeleteUser(t *testing.T) {
database.DropTables() database.DropTables()
database.MigrateModels() database.MigrateModels()
err, adminpw := database.DBAddAdminUser(configuration.GlobalConfig) adminpw, err := database.DBAddAdminUser(configuration.GlobalConfig)
assert.NoError(t, err) assert.NoError(t, err)
// authenticate as admin // authenticate as admin
@ -799,7 +799,7 @@ func TestDeleteUser(t *testing.T) {
// try to DELETE with invalid ID // try to DELETE with invalid ID
// should result in bad request // should result in bad request
code, resp, err = helper.TestEndpoint(router, token, code, resp, err = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/users/bla"), "DELETE", nil) "/api/v2/users/bla", "DELETE", nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)

View file

@ -82,16 +82,16 @@ func (r *updateUserRequest) updatedUser(callerID interface{}, role interface{},
// Only the Admin must be able to update user's role // Only the Admin must be able to update user's role
if role != "Admin" && r.User.Role != "" { if role != "Admin" && r.User.Role != "" {
if r.User.Role != u.Role { if r.User.Role != u.Role {
return u, fmt.Errorf("Only Admin can update user's Role") return u, fmt.Errorf("only Admin can update user's Role")
} }
} else if role == "Admin" && r.User.Role != "" { } else if role == "Admin" && r.User.Role != "" {
u.Role = r.User.Role u.Role = r.User.Role
} }
// Only the Admin must be able to update users Active state // Only the Admin must be able to update users Active state
if (r.User.Active == "yes" && u.Active == false) || (r.User.Active == "no" && u.Active == true) { if (r.User.Active == "yes" && !u.Active) || (r.User.Active == "no" && u.Active) {
if role != "Admin" { if role != "Admin" {
return u, fmt.Errorf("Only Admin can update user's Active state") return u, fmt.Errorf("only Admin can update user's Active state")
} else { } else {
u.Active = !u.Active u.Active = !u.Active
} }
@ -100,7 +100,7 @@ func (r *updateUserRequest) updatedUser(callerID interface{}, role interface{},
// Update the username making sure it is NOT taken // Update the username making sure it is NOT taken
var testUser User var testUser User
if err := testUser.ByUsername(r.User.Username); err == nil { if err := testUser.ByUsername(r.User.Username); err == nil {
return u, fmt.Errorf("Username is alreaday taken") return u, fmt.Errorf("username is alreaday taken")
} }
if r.User.Username != "" { if r.User.Username != "" {

View file

@ -87,7 +87,9 @@ func addScenarioAndDashboard(token string) (scenarioID uint, dashboardID uint) {
// POST $newScenario // POST $newScenario
newScenario := ScenarioRequest{ newScenario := ScenarioRequest{
Name: "Scenario1", Name: "Scenario1",
StartParameters: postgres.Jsonb{json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)}, StartParameters: postgres.Jsonb{
RawMessage: json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`),
},
} }
_, resp, _ := helper.TestEndpoint(router, token, _, resp, _ := helper.TestEndpoint(router, token,
"/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario}) "/api/v2/scenarios", "POST", helper.KeyModels{"scenario": newScenario})
@ -108,7 +110,7 @@ func addScenarioAndDashboard(token string) (scenarioID uint, dashboardID uint) {
newDashboardID, _ := helper.GetResponseID(resp) newDashboardID, _ := helper.GetResponseID(resp)
// add the guest user to the new scenario // add the guest user to the new scenario
_, resp, _ = helper.TestEndpoint(router, token, _, _, _ = helper.TestEndpoint(router, token,
fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil) fmt.Sprintf("/api/v2/scenarios/%v/user?username=User_C", newScenarioID), "PUT", nil)
return uint(newScenarioID), uint(newDashboardID) return uint(newScenarioID), uint(newDashboardID)

View file

@ -135,7 +135,7 @@ func main() {
} }
// Make sure that at least one admin user exists in DB // Make sure that at least one admin user exists in DB
err, _ = database.DBAddAdminUser(configuration.GlobalConfig) _, err = database.DBAddAdminUser(configuration.GlobalConfig)
if err != nil { if err != nil {
fmt.Println("error: adding admin user failed:", err.Error()) fmt.Println("error: adding admin user failed:", err.Error())
log.Fatal(err) log.Fatal(err)