Commit f3a7ed0e authored by Sonja Happ's avatar Sonja Happ
Browse files

**Major revision of repository structure**

- rename common package to database
- move all code not related to database to new helper package
- add more test in database package to improve code coverage
- add a new (own) package for AMQP client
parent 451cd32d
package common
package amqp
import (
"encoding/json"
"fmt"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/database"
"github.com/streadway/amqp"
"github.com/tidwall/gjson"
"strings"
......@@ -97,8 +98,8 @@ func ConnectAMQP(uri string) error {
continue
}
var sToBeUpdated Simulator
db := GetDB()
var sToBeUpdated database.Simulator
db := database.GetDB()
err = db.Where("UUID = ?", gjson.Get(content, "properties.uuid")).Find(sToBeUpdated).Error
if err != nil {
fmt.Println("AMQP: Unable to find simulator with UUID: ", gjson.Get(content, "properties.uuid"), " DB error message: ", err)
......
package common
package database
import (
"flag"
......@@ -36,7 +36,9 @@ func InitDB(dbname string) *gorm.DB {
dbinfo := fmt.Sprintf("host=%s sslmode=%s dbname=%s",
DB_HOST, DB_SSLMODE, dbname)
db, err := gorm.Open("postgres", dbinfo)
checkErr(err)
if err != nil {
log.Fatal(err)
}
DBpool = db
if dbname == DB_TEST {
......@@ -80,11 +82,3 @@ func MigrateModels(db *gorm.DB) {
db.AutoMigrate(&Dashboard{})
db.AutoMigrate(&Widget{})
}
// Quick error check
// NOTE: maybe this is not a good idea
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
package common
package database
import (
"fmt"
......@@ -355,3 +355,24 @@ func TestFileAssociations(t *testing.T) {
assert.NoError(t, db.Find(&file1, 1).Error, fmt.Sprintf("Find File with ID=1"))
assert.EqualValues(t, "File_A", file1.Name)
}
func TestAddAdmin(t *testing.T) {
DropTables(db)
MigrateModels(db)
assert.NoError(t, DBAddAdminUser(db))
}
func TestAddAdminAndUsers(t *testing.T) {
DropTables(db)
MigrateModels(db)
assert.NoError(t, DBAddAdminAndUser(db))
}
func TestAddData(t *testing.T) {
DropTables(db)
MigrateModels(db)
assert.NoError(t, DBAddTestData(db))
}
package common
package database
import (
"time"
......
package common
package database
import (
"fmt"
......
package database
import (
"encoding/json"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
"golang.org/x/crypto/bcrypt"
"time"
)
// #######################################################################
// #################### Data used for testing ############################
// #######################################################################
// Users
var StrPassword0 = "xyz789"
var StrPasswordA = "abc123"
var StrPasswordB = "bcd234"
// Hash passwords with bcrypt algorithm
var bcryptCost = 10
var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost)
var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost)
var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost)
var User0 = User{Username: "User_0", Password: string(pw0),
Role: "Admin", Mail: "User_0@example.com"}
var UserA = User{Username: "User_A", Password: string(pwA),
Role: "User", Mail: "User_A@example.com"}
var UserB = User{Username: "User_B", Password: string(pwB),
Role: "User", Mail: "User_B@example.com"}
// Simulators
var propertiesA = json.RawMessage(`{"name" : "TestNameA", "category" : "CategoryA", "location" : "anywhere on earth", "type": "dummy"}`)
var propertiesB = json.RawMessage(`{"name" : "TestNameB", "category" : "CategoryB", "location" : "where ever you want", "type": "generic"}`)
var SimulatorA = Simulator{
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
Host: "Host_A",
Modeltype: "ModelTypeA",
Uptime: 0,
State: "running",
StateUpdateAt: time.Now().String(),
Properties: postgres.Jsonb{propertiesA},
RawProperties: postgres.Jsonb{propertiesA},
}
var SimulatorB = Simulator{
UUID: "7be0322d-354e-431e-84bd-ae4c9633138b",
Host: "Host_B",
Modeltype: "ModelTypeB",
Uptime: 0,
State: "idle",
StateUpdateAt: time.Now().String(),
Properties: postgres.Jsonb{propertiesB},
RawProperties: postgres.Jsonb{propertiesB},
}
// Scenarios
var startParametersA = json.RawMessage(`{"parameter1" : "testValue1A", "parameter2" : "testValue2A", "parameter3" : 42}`)
var startParametersB = json.RawMessage(`{"parameter1" : "testValue1B", "parameter2" : "testValue2B", "parameter3" : 43}`)
var ScenarioA = Scenario{
Name: "Scenario_A",
Running: true,
StartParameters: postgres.Jsonb{startParametersA},
}
var ScenarioB = Scenario{
Name: "Scenario_B",
Running: false,
StartParameters: postgres.Jsonb{startParametersB},
}
// Simulation Models
var SimulationModelA = SimulationModel{
Name: "SimulationModel_A",
StartParameters: postgres.Jsonb{startParametersA},
}
var SimulationModelB = SimulationModel{
Name: "SimulationModel_B",
StartParameters: postgres.Jsonb{startParametersB},
}
// Signals
var OutSignalA = Signal{
Name: "outSignal_A",
Direction: "out",
Index: 0,
Unit: "V",
}
var OutSignalB = Signal{
Name: "outSignal_B",
Direction: "out",
Index: 1,
Unit: "V",
}
var InSignalA = Signal{
Name: "inSignal_A",
Direction: "in",
Index: 0,
Unit: "A",
}
var InSignalB = Signal{
Name: "inSignal_B",
Direction: "in",
Index: 1,
Unit: "A",
}
// Dashboards
var DashboardA = Dashboard{
Name: "Dashboard_A",
Grid: 15,
}
var DashboardB = Dashboard{
Name: "Dashboard_B",
Grid: 10,
}
// Files
var FileA = File{
Name: "File_A",
Type: "text/plain",
Size: 42,
ImageHeight: 333,
ImageWidth: 111,
Date: time.Now().String(),
}
var FileB = File{
Name: "File_B",
Type: "text/plain",
Size: 1234,
ImageHeight: 55,
ImageWidth: 22,
Date: time.Now().String(),
}
var FileC = File{
Name: "File_C",
Type: "text/plain",
Size: 32,
ImageHeight: 10,
ImageWidth: 10,
Date: time.Now().String(),
}
var FileD = File{
Name: "File_D",
Type: "text/plain",
Size: 5000,
ImageHeight: 400,
ImageWidth: 800,
Date: time.Now().String(),
}
// Widgets
var customPropertiesA = json.RawMessage(`{"property1" : "testValue1A", "property2" : "testValue2A", "property3" : 42}`)
var customPropertiesB = json.RawMessage(`{"property1" : "testValue1B", "property2" : "testValue2B", "property3" : 43}`)
var WidgetA = Widget{
Name: "Widget_A",
Type: "graph",
Width: 100,
Height: 50,
MinHeight: 40,
MinWidth: 80,
X: 10,
Y: 10,
Z: 10,
IsLocked: false,
CustomProperties: postgres.Jsonb{customPropertiesA},
}
var WidgetB = Widget{
Name: "Widget_B",
Type: "slider",
Width: 200,
Height: 20,
MinHeight: 10,
MinWidth: 50,
X: 100,
Y: -40,
Z: -1,
IsLocked: false,
CustomProperties: postgres.Jsonb{customPropertiesB},
}
func DBAddAdminUser(db *gorm.DB) error {
db.AutoMigrate(&User{})
//create a copy of global test data
user0 := User0
// add admin user to DB
err := db.Create(&user0).Error
return err
}
func DBAddAdminAndUser(db *gorm.DB) error {
db.AutoMigrate(&User{})
//create a copy of global test data
user0 := User0
userA := UserA
userB := UserB
// add admin user to DB
err := db.Create(&user0).Error
// add normal users to DB
err = db.Create(&userA).Error
err = db.Create(&userB).Error
return err
}
// Populates DB with test data
func DBAddTestData(db *gorm.DB) error {
MigrateModels(db)
// Create entries of each model (data defined in testdata.go)
//create a copy of global test data
user0 := User0
userA := UserA
userB := UserB
simulatorA := SimulatorA
simulatorB := SimulatorB
scenarioA := ScenarioA
scenarioB := ScenarioB
outSignalA := OutSignalA
outSignalB := OutSignalB
inSignalA := InSignalA
inSignalB := InSignalB
modelA := SimulationModelA
modelB := SimulationModelB
dashboardA := DashboardA
dashboardB := DashboardB
fileA := FileA
fileB := FileB
fileC := FileC
fileD := FileD
widgetA := WidgetA
widgetB := WidgetB
// Users
err := db.Create(&user0).Error
// add normal users to DB
err = db.Create(&userA).Error
err = db.Create(&userB).Error
// Simulators
err = db.Create(&simulatorA).Error
err = db.Create(&simulatorB).Error
// Scenarios
err = db.Create(&scenarioA).Error
err = db.Create(&scenarioB).Error
// Signals
err = db.Create(&inSignalA).Error
err = db.Create(&inSignalB).Error
err = db.Create(&outSignalA).Error
err = db.Create(&outSignalB).Error
// Simulation Models
err = db.Create(&modelA).Error
err = db.Create(&modelB).Error
// Dashboards
err = db.Create(&dashboardA).Error
err = db.Create(&dashboardB).Error
// Files
err = db.Create(&fileA).Error
err = db.Create(&fileB).Error
err = db.Create(&fileC).Error
err = db.Create(&fileD).Error
// Widgets
err = db.Create(&widgetA).Error
err = db.Create(&widgetB).Error
// Associations between models
// For `belongs to` use the model with id=1
// For `has many` use the models with id=1 and id=2
// User HM Scenarios, Scenario HM Users (Many-to-Many)
err = db.Model(&scenarioA).Association("Users").Append(&userA).Error
err = db.Model(&scenarioB).Association("Users").Append(&userA).Error
err = db.Model(&scenarioB).Association("Users").Append(&userB).Error
// Scenario HM SimulationModels
err = db.Model(&scenarioA).Association("SimulationModels").Append(&modelA).Error
err = db.Model(&scenarioA).Association("SimulationModels").Append(&modelB).Error
// Scenario HM Dashboards
err = db.Model(&scenarioA).Association("Dashboards").Append(&dashboardA).Error
err = db.Model(&scenarioA).Association("Dashboards").Append(&dashboardB).Error
// Dashboard HM Widget
err = db.Model(&dashboardA).Association("Widgets").Append(&widgetA).Error
err = db.Model(&dashboardA).Association("Widgets").Append(&widgetB).Error
// SimulationModel HM Signals
err = db.Model(&modelA).Association("InputMapping").Append(&inSignalA).Error
err = db.Model(&modelA).Association("InputMapping").Append(&inSignalB).Error
err = db.Model(&modelA).Association("InputMapping").Append(&outSignalA).Error
err = db.Model(&modelA).Association("InputMapping").Append(&outSignalB).Error
// SimulationModel HM Files
err = db.Model(&modelA).Association("Files").Append(&fileC).Error
err = db.Model(&modelA).Association("Files").Append(&fileD).Error
// Simulator HM SimulationModels
err = db.Model(&simulatorA).Association("SimulationModels").Append(&modelA).Error
err = db.Model(&simulatorA).Association("SimulationModels").Append(&modelB).Error
// Widget HM Files
err = db.Model(&widgetA).Association("Files").Append(&fileA).Error
err = db.Model(&widgetA).Association("Files").Append(&fileB).Error
return err
}
package docs
import "git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
import "git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/database"
// This file defines the responses to any endpoint in the backend
// The defined structures are only used for documentation purposes with swaggo and are NOT used in the code
......@@ -14,69 +14,69 @@ type ResponseAuthenticate struct {
success bool
token string
message string
user common.User
user database.User
}
type ResponseUsers struct {
users []common.User
users []database.User
}
type ResponseUser struct {
user common.User
user database.User
}
type ResponseSimulators struct {
simulators []common.Simulator
simulators []database.Simulator
}
type ResponseSimulator struct {
simulator common.Simulator
simulator database.Simulator
}
type ResponseScenarios struct {
scenarios []common.Scenario
scenarios []database.Scenario
}
type ResponseScenario struct {
scenario common.Scenario
scenario database.Scenario
}
type ResponseSimulationModels struct {
models []common.SimulationModel
models []database.SimulationModel
}
type ResponseSimulationModel struct {
model common.SimulationModel
model database.SimulationModel
}
type ResponseDashboards struct {
dashboards []common.Dashboard
dashboards []database.Dashboard
}
type ResponseDashboard struct {
dashboard common.Dashboard
dashboard database.Dashboard
}
type ResponseWidgets struct {
widgets []common.Widget
widgets []database.Widget
}
type ResponseWidget struct {
widget common.Widget
widget database.Widget
}
type ResponseSignals struct {
signals []common.Signal
signals []database.Signal
}
type ResponseSignal struct {
signal common.Signal
signal database.Signal
}
type ResponseFiles struct {
files []common.File
files []database.File
}
type ResponseFile struct {
file common.File
file database.File
}
package common
package helper
import (
"fmt"
......
package common
package helper
import (
"bytes"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
"github.com/nsf/jsondiff"
"golang.org/x/crypto/bcrypt"
"log"
"net/http"
"net/http/httptest"
"time"
)
// data type used in testing
type KeyModels map[string]interface{}
// #######################################################################
// #################### Data used for testing ############################
// #################### User data used for testing #######################
// #######################################################################
// Users
// Credentials
var StrPassword0 = "xyz789"
var StrPasswordA = "abc123"
var StrPasswordB = "bcd234"
// Hash passwords with bcrypt algorithm
var bcryptCost = 10
var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost)
var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost)
var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost)
var User0 = User{Username: "User_0", Password: string(pw0),
Role: "Admin", Mail: "User_0@example.com"}
var UserA = User{Username: "User_A", Password: string(pwA),
Role: "User", Mail: "User_A@example.com"}
var UserB = User{Username: "User_B", Password: string(pwB),
Role: "User", Mail: "User_B@example.com"}
// Credentials
type Credentials struct {
Username string
Password string
}
var AdminCredentials = Credentials{
Username: User0.Username,
Username: "User_0",
Password: StrPassword0,
}
var UserACredentials = Credentials{
Username: UserA.Username,
Username: "User_A",
Password: StrPasswordA,
}
var UserBCredentials = Credentials{
Username: UserB.Username,
Username: "User_B",
Password: StrPasswordB,
}
// Simulators
var propertiesA = json.RawMessage(`{"name" : "TestNameA", "category" : "CategoryA", "location" : "anywhere on earth", "type": "dummy"}`)
var propertiesB = json.RawMessage(`{"name" : "TestNameB", "category" : "CategoryB", "location" : "where ever you want", "type": "generic"}`)
var SimulatorA = Simulator{
UUID: "4854af30-325f-44a5-ad59-b67b2597de68",
Host: "Host_A",
Modeltype: "ModelTypeA",
Uptime: 0,
State: "running",
StateUpdateAt: time.Now().String(),