mirror of
https://git.rwth-aachen.de/acs/public/villas/web-backend-go/
synced 2025-03-30 00:00:12 +01:00
move functions to duplicate scenarios into respective packages, resolve circular dependency problems (move permissions checking to database package), improve error handling of async DuplicateScenarioForUser function
This commit is contained in:
parent
93d14300d8
commit
302b1cc470
42 changed files with 1051 additions and 887 deletions
|
@ -176,3 +176,67 @@ func generatePassword(Len int) string {
|
|||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// add test users defined above
|
||||
func AddTestUsers() error {
|
||||
|
||||
testUsers := []User{User0, UserA, UserB, UserC}
|
||||
DBpool.AutoMigrate(&User{})
|
||||
|
||||
for _, user := range testUsers {
|
||||
err := DBpool.Create(&user).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Credentials
|
||||
var StrPassword0 = "xyz789"
|
||||
var StrPasswordA = "abc123"
|
||||
var StrPasswordB = "bcd234"
|
||||
var StrPasswordC = "guestpw"
|
||||
|
||||
// Hash passwords with bcrypt algorithm
|
||||
var bcryptCost = 10
|
||||
var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost)
|
||||
var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost)
|
||||
var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost)
|
||||
var pwC, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordC), bcryptCost)
|
||||
|
||||
var User0 = 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", Active: true}
|
||||
var UserB = User{Username: "User_B", Password: string(pwB),
|
||||
Role: "User", Mail: "User_B@example.com", Active: true}
|
||||
var UserC = User{Username: "User_C", Password: string(pwC),
|
||||
Role: "Guest", Mail: "User_C@example.com", Active: true}
|
||||
|
||||
type Credentials struct {
|
||||
Username string `json:"username,required"`
|
||||
Password string `json:"password,required"`
|
||||
}
|
||||
|
||||
var AdminCredentials = Credentials{
|
||||
Username: User0.Username,
|
||||
Password: StrPassword0,
|
||||
}
|
||||
|
||||
var UserACredentials = Credentials{
|
||||
Username: UserA.Username,
|
||||
Password: StrPasswordA,
|
||||
}
|
||||
|
||||
var UserBCredentials = Credentials{
|
||||
Username: UserB.Username,
|
||||
Password: StrPasswordB,
|
||||
}
|
||||
|
||||
var GuestCredentials = Credentials{
|
||||
Username: UserC.Username,
|
||||
Password: StrPasswordC,
|
||||
}
|
||||
|
|
301
database/permissions.go
Normal file
301
database/permissions.go
Normal file
|
@ -0,0 +1,301 @@
|
|||
/** Database package, roles.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CheckScenarioPermissions(c *gin.Context, operation CRUD, scenarioIDsource string, scenarioIDbody int) (bool, Scenario) {
|
||||
|
||||
var so Scenario
|
||||
|
||||
err := ValidateRole(c, ModelScenario, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of scenario failed): %v", err))
|
||||
return false, so
|
||||
}
|
||||
|
||||
if operation == Create || (operation == Read && scenarioIDsource == "none") {
|
||||
return true, so
|
||||
}
|
||||
|
||||
scenarioID, err := helper.GetIDOfElement(c, "scenarioID", scenarioIDsource, scenarioIDbody)
|
||||
if err != nil {
|
||||
return false, so
|
||||
}
|
||||
|
||||
userID, _ := c.Get(UserIDCtx)
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&so, uint(scenarioID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, so
|
||||
}
|
||||
|
||||
hasAccess := false
|
||||
u := User{}
|
||||
|
||||
err = db.Find(&u, userID.(uint)).Error
|
||||
if err != nil {
|
||||
hasAccess = false
|
||||
}
|
||||
|
||||
if u.Role == "Admin" {
|
||||
hasAccess = true
|
||||
}
|
||||
|
||||
scenarioUser := User{}
|
||||
err = db.Order("ID asc").Model(&so).Where("ID = ?", userID.(uint)).Related(&scenarioUser, "Users").Error
|
||||
if err != nil {
|
||||
hasAccess = false
|
||||
}
|
||||
|
||||
if !scenarioUser.Active {
|
||||
hasAccess = false
|
||||
} else if so.IsLocked && operation != Read {
|
||||
hasAccess = false
|
||||
} else {
|
||||
hasAccess = true
|
||||
}
|
||||
|
||||
if hasAccess == false {
|
||||
helper.UnprocessableEntityError(c, "Access denied (user has no access or scenario is locked).")
|
||||
return false, so
|
||||
}
|
||||
|
||||
return true, so
|
||||
|
||||
}
|
||||
|
||||
func CheckComponentConfigPermissions(c *gin.Context, operation CRUD, configIDSource string, configIDBody int) (bool, ComponentConfiguration) {
|
||||
|
||||
var m ComponentConfiguration
|
||||
|
||||
err := ValidateRole(c, ModelComponentConfiguration, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of Component Configuration failed): %v", err.Error()))
|
||||
return false, m
|
||||
}
|
||||
|
||||
configID, err := helper.GetIDOfElement(c, "configID", configIDSource, configIDBody)
|
||||
if err != nil {
|
||||
return false, m
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&m, uint(configID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, m
|
||||
}
|
||||
|
||||
ok, _ := CheckScenarioPermissions(c, operation, "body", int(m.ScenarioID))
|
||||
if !ok {
|
||||
return false, m
|
||||
}
|
||||
|
||||
return true, m
|
||||
|
||||
}
|
||||
|
||||
func CheckSignalPermissions(c *gin.Context, operation CRUD) (bool, Signal) {
|
||||
|
||||
var sig Signal
|
||||
|
||||
err := ValidateRole(c, ModelSignal, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of signal failed): %v", err.Error()))
|
||||
return false, sig
|
||||
}
|
||||
|
||||
signalID, err := helper.GetIDOfElement(c, "signalID", "path", -1)
|
||||
if err != nil {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&sig, uint(signalID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
ok, _ := CheckComponentConfigPermissions(c, operation, "body", int(sig.ConfigID))
|
||||
if !ok {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
return true, sig
|
||||
|
||||
}
|
||||
|
||||
func CheckDashboardPermissions(c *gin.Context, operation CRUD, dabIDSource string, dabIDBody int) (bool, Dashboard) {
|
||||
|
||||
var dab Dashboard
|
||||
|
||||
err := ValidateRole(c, ModelDashboard, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation failed): %v", err.Error()))
|
||||
return false, dab
|
||||
}
|
||||
|
||||
dabID, err := helper.GetIDOfElement(c, "dashboardID", dabIDSource, dabIDBody)
|
||||
if err != nil {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&dab, uint(dabID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
ok, _ := CheckScenarioPermissions(c, operation, "body", int(dab.ScenarioID))
|
||||
if !ok {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
return true, dab
|
||||
|
||||
}
|
||||
|
||||
func CheckWidgetPermissions(c *gin.Context, operation CRUD, widgetIDBody int) (bool, Widget) {
|
||||
|
||||
var w Widget
|
||||
var err error
|
||||
err = ValidateRole(c, ModelWidget, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of widget failed): %v", err.Error()))
|
||||
return false, w
|
||||
}
|
||||
|
||||
var widgetID int
|
||||
if widgetIDBody < 0 {
|
||||
widgetID, err = helper.GetIDOfElement(c, "widgetID", "path", -1)
|
||||
if err != nil {
|
||||
return false, w
|
||||
}
|
||||
} else {
|
||||
widgetID = widgetIDBody
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&w, uint(widgetID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, w
|
||||
}
|
||||
|
||||
ok, _ := CheckDashboardPermissions(c, operation, "body", int(w.DashboardID))
|
||||
if !ok {
|
||||
return false, w
|
||||
}
|
||||
|
||||
return true, w
|
||||
}
|
||||
|
||||
func CheckFilePermissions(c *gin.Context, operation CRUD) (bool, File) {
|
||||
|
||||
var f File
|
||||
|
||||
err := ValidateRole(c, ModelFile, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of file failed): %v", err.Error()))
|
||||
return false, f
|
||||
}
|
||||
|
||||
fileID, err := helper.GetIDOfElement(c, "fileID", "path", -1)
|
||||
if err != nil {
|
||||
return false, f
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&f, uint(fileID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, f
|
||||
}
|
||||
|
||||
if operation != Read {
|
||||
// check access to scenario only if operation is not Read (=download) of file
|
||||
ok, _ := CheckScenarioPermissions(c, operation, "body", int(f.ScenarioID))
|
||||
if !ok {
|
||||
return false, f
|
||||
}
|
||||
}
|
||||
|
||||
return true, f
|
||||
}
|
||||
|
||||
func CheckResultPermissions(c *gin.Context, operation CRUD, resultIDSource string, resultIDBody int) (bool, Result) {
|
||||
|
||||
var result Result
|
||||
|
||||
err := ValidateRole(c, ModelResult, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation failed): %v", err.Error()))
|
||||
return false, result
|
||||
}
|
||||
|
||||
resultID, err := helper.GetIDOfElement(c, "resultID", resultIDSource, resultIDBody)
|
||||
if err != nil {
|
||||
return false, result
|
||||
}
|
||||
|
||||
db := GetDB()
|
||||
err = db.Find(&result, uint(resultID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, result
|
||||
}
|
||||
|
||||
ok, _ := CheckScenarioPermissions(c, operation, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return false, result
|
||||
}
|
||||
|
||||
return true, result
|
||||
}
|
||||
|
||||
func CheckICPermissions(c *gin.Context, modeltype ModelName, operation CRUD, hasID bool) (bool, InfrastructureComponent) {
|
||||
|
||||
var s InfrastructureComponent
|
||||
|
||||
err := ValidateRole(c, modeltype, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of infrastructure component failed): %v", err.Error()))
|
||||
return false, s
|
||||
}
|
||||
|
||||
if hasID {
|
||||
// Get the ID of the infrastructure component from the context
|
||||
ICID, err := helper.GetIDOfElement(c, "ICID", "path", -1)
|
||||
if err != nil {
|
||||
return false, s
|
||||
}
|
||||
db := GetDB()
|
||||
err = db.Find(&s, uint(ICID)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return false, s
|
||||
}
|
||||
}
|
||||
|
||||
return true, s
|
||||
}
|
|
@ -23,7 +23,6 @@ package database
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
|
|
@ -25,10 +25,8 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nsf/jsondiff"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -41,28 +39,6 @@ type KeyModels map[string]interface{}
|
|||
// #################### User data used for testing #######################
|
||||
// #######################################################################
|
||||
|
||||
// Credentials
|
||||
var StrPassword0 = "xyz789"
|
||||
var StrPasswordA = "abc123"
|
||||
var StrPasswordB = "bcd234"
|
||||
var StrPasswordC = "guestpw"
|
||||
|
||||
// Hash passwords with bcrypt algorithm
|
||||
var bcryptCost = 10
|
||||
var pw0, _ = bcrypt.GenerateFromPassword([]byte(StrPassword0), bcryptCost)
|
||||
var pwA, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordA), bcryptCost)
|
||||
var pwB, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordB), bcryptCost)
|
||||
var pwC, _ = bcrypt.GenerateFromPassword([]byte(StrPasswordC), bcryptCost)
|
||||
|
||||
var User0 = database.User{Username: "User_0", Password: string(pw0),
|
||||
Role: "Admin", Mail: "User_0@example.com"}
|
||||
var UserA = database.User{Username: "User_A", Password: string(pwA),
|
||||
Role: "User", Mail: "User_A@example.com", Active: true}
|
||||
var UserB = database.User{Username: "User_B", Password: string(pwB),
|
||||
Role: "User", Mail: "User_B@example.com", Active: true}
|
||||
var UserC = database.User{Username: "User_C", Password: string(pwC),
|
||||
Role: "Guest", Mail: "User_C@example.com", Active: true}
|
||||
|
||||
type UserRequest struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
|
@ -72,31 +48,6 @@ type UserRequest struct {
|
|||
Active string `json:"active,omitempty"`
|
||||
}
|
||||
|
||||
type Credentials struct {
|
||||
Username string `json:"username,required"`
|
||||
Password string `json:"password,required"`
|
||||
}
|
||||
|
||||
var AdminCredentials = Credentials{
|
||||
Username: User0.Username,
|
||||
Password: StrPassword0,
|
||||
}
|
||||
|
||||
var UserACredentials = Credentials{
|
||||
Username: UserA.Username,
|
||||
Password: StrPasswordA,
|
||||
}
|
||||
|
||||
var UserBCredentials = Credentials{
|
||||
Username: UserB.Username,
|
||||
Password: StrPasswordB,
|
||||
}
|
||||
|
||||
var GuestCredentials = Credentials{
|
||||
Username: UserC.Username,
|
||||
Password: StrPasswordC,
|
||||
}
|
||||
|
||||
// ############################################################################
|
||||
// #################### Functions used for testing ############################
|
||||
// ############################################################################
|
||||
|
@ -314,20 +265,3 @@ func AuthenticateForTest(router *gin.Engine, credentials interface{}) (string, e
|
|||
// Return the token and nil error
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// add test users defined above
|
||||
func AddTestUsers() error {
|
||||
|
||||
testUsers := []database.User{User0, UserA, UserB, UserC}
|
||||
database.DBpool.AutoMigrate(&database.User{})
|
||||
|
||||
for _, user := range testUsers {
|
||||
err := database.DBpool.Create(&user).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
)
|
||||
|
||||
func RegisterComponentConfigurationEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -54,7 +53,7 @@ func RegisterComponentConfigurationEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getConfigs(c *gin.Context) {
|
||||
|
||||
ok, so := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, so := database.CheckScenarioPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -102,7 +101,7 @@ func addConfig(c *gin.Context) {
|
|||
newConfig := req.createConfig()
|
||||
|
||||
// check access to the scenario
|
||||
ok, _ := scenario.CheckPermissions(c, database.Update, "body", int(newConfig.ScenarioID))
|
||||
ok, _ := database.CheckScenarioPermissions(c, database.Update, "body", int(newConfig.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -132,11 +131,15 @@ func addConfig(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateConfig(c *gin.Context) {
|
||||
|
||||
ok, oldConfig := CheckPermissions(c, database.Update, "path", -1)
|
||||
ok, oldConfig_r := database.CheckComponentConfigPermissions(c, database.Update, "path", -1)
|
||||
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldConfig ComponentConfiguration
|
||||
oldConfig.ComponentConfiguration = oldConfig_r
|
||||
|
||||
var req updateConfigRequest
|
||||
err := c.BindJSON(&req)
|
||||
if err != nil {
|
||||
|
@ -176,12 +179,12 @@ func updateConfig(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getConfig(c *gin.Context) {
|
||||
|
||||
ok, m := CheckPermissions(c, database.Read, "path", -1)
|
||||
ok, m := database.CheckComponentConfigPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"config": m.ComponentConfiguration})
|
||||
c.JSON(http.StatusOK, gin.H{"config": m})
|
||||
}
|
||||
|
||||
// deleteConfig godoc
|
||||
|
@ -199,11 +202,14 @@ func getConfig(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteConfig(c *gin.Context) {
|
||||
|
||||
ok, m := CheckPermissions(c, database.Delete, "path", -1)
|
||||
ok, m_r := database.CheckComponentConfigPermissions(c, database.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var m ComponentConfiguration
|
||||
m.ComponentConfiguration = m_r
|
||||
|
||||
err := m.delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"config": m.ComponentConfiguration})
|
||||
|
|
|
@ -23,7 +23,7 @@ package component_configuration
|
|||
|
||||
import (
|
||||
"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/signal"
|
||||
"log"
|
||||
)
|
||||
|
||||
|
@ -48,8 +48,8 @@ func (m *ComponentConfiguration) ByID(id uint) error {
|
|||
|
||||
func (m *ComponentConfiguration) addToScenario() error {
|
||||
db := database.GetDB()
|
||||
var so scenario.Scenario
|
||||
err := so.ByID(m.ScenarioID)
|
||||
var so database.Scenario
|
||||
err := db.Find(&so, m.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ func (m *ComponentConfiguration) Update(modifiedConfig ComponentConfiguration) e
|
|||
func (m *ComponentConfiguration) delete() error {
|
||||
|
||||
db := database.GetDB()
|
||||
var so scenario.Scenario
|
||||
err := so.ByID(m.ScenarioID)
|
||||
var so database.Scenario
|
||||
err := db.Find(&so, m.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -185,3 +185,53 @@ func (m *ComponentConfiguration) delete() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ComponentConfiguration) Duplicate(scenarioID uint, icIds map[uint]string, signalMap *map[uint]uint) error {
|
||||
|
||||
db := database.GetDB()
|
||||
|
||||
var dup ComponentConfiguration
|
||||
dup.Name = m.Name
|
||||
dup.StartParameters = m.StartParameters
|
||||
dup.ScenarioID = scenarioID
|
||||
|
||||
if icIds[m.ICID] == "" {
|
||||
dup.ICID = m.ICID
|
||||
} else {
|
||||
var duplicatedIC database.InfrastructureComponent
|
||||
err := db.Find(&duplicatedIC, "UUID = ?", icIds[m.ICID]).Error
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
}
|
||||
dup.ICID = duplicatedIC.ID
|
||||
}
|
||||
|
||||
// save duplicate to DB and create associations with IC and scenario
|
||||
err := dup.addToScenario()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// duplication of signals
|
||||
var sigs []signal.Signal
|
||||
err = db.Order("ID asc").Model(&m).Related(&sigs, "OutputMapping").Error
|
||||
smap := *signalMap
|
||||
for _, s := range sigs {
|
||||
var sigDup signal.Signal
|
||||
sigDup.Direction = s.Direction
|
||||
sigDup.Index = s.Index
|
||||
sigDup.Name = s.Name // + ` ` + userName
|
||||
sigDup.ScalingFactor = s.ScalingFactor
|
||||
sigDup.Unit = s.Unit
|
||||
sigDup.ConfigID = dup.ID
|
||||
err = sigDup.AddToConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smap[s.ID] = sigDup.ID
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/** component_configuration package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package component_configuration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD, configIDSource string, configIDBody int) (bool, ComponentConfiguration) {
|
||||
|
||||
var m ComponentConfiguration
|
||||
|
||||
err := database.ValidateRole(c, database.ModelComponentConfiguration, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of Component Configuration failed): %v", err.Error()))
|
||||
return false, m
|
||||
}
|
||||
|
||||
configID, err := helper.GetIDOfElement(c, "configID", configIDSource, configIDBody)
|
||||
if err != nil {
|
||||
return false, m
|
||||
}
|
||||
|
||||
err = m.ByID(uint(configID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, m
|
||||
}
|
||||
|
||||
ok, _ := scenario.CheckPermissions(c, operation, "body", int(m.ScenarioID))
|
||||
if !ok {
|
||||
return false, m
|
||||
}
|
||||
|
||||
return true, m
|
||||
}
|
|
@ -81,7 +81,7 @@ func newFalse() *bool {
|
|||
func addScenarioAndIC() (scenarioID uint, ICID uint) {
|
||||
|
||||
// authenticate as admin
|
||||
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, _ := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
|
||||
// POST $newICA
|
||||
newICA := ICRequest{
|
||||
|
@ -114,7 +114,7 @@ func addScenarioAndIC() (scenarioID uint, ICID uint) {
|
|||
}
|
||||
|
||||
// authenticate as normal user
|
||||
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, _ = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
|
||||
// POST $newScenario
|
||||
newScenario := ScenarioRequest{
|
||||
|
@ -168,7 +168,7 @@ func TestMain(m *testing.M) {
|
|||
func TestAddConfig(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -178,7 +178,7 @@ func TestAddConfig(t *testing.T) {
|
|||
newConfig1.ScenarioID = scenarioID
|
||||
newConfig1.ICID = ICID
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST with no access
|
||||
|
@ -189,7 +189,7 @@ func TestAddConfig(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST non JSON body
|
||||
|
@ -199,7 +199,7 @@ func TestAddConfig(t *testing.T) {
|
|||
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newConfig
|
||||
|
@ -238,7 +238,7 @@ func TestAddConfig(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try to GET the newConfig with no access
|
||||
|
@ -254,7 +254,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -262,7 +262,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
scenarioID, ICID := addScenarioAndIC()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newConfig
|
||||
|
@ -283,7 +283,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT with no access
|
||||
|
@ -294,7 +294,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user who has access to component config
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT as guest
|
||||
|
@ -305,7 +305,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT a non JSON body
|
||||
|
@ -357,7 +357,7 @@ func TestUpdateConfig(t *testing.T) {
|
|||
func TestDeleteConfig(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -367,7 +367,7 @@ func TestDeleteConfig(t *testing.T) {
|
|||
newConfig1.ICID = ICID
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newConfig
|
||||
|
@ -381,7 +381,7 @@ func TestDeleteConfig(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to DELETE with no access
|
||||
|
@ -392,7 +392,7 @@ func TestDeleteConfig(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the component config returned for scenario
|
||||
|
@ -421,7 +421,7 @@ func TestDeleteConfig(t *testing.T) {
|
|||
func TestGetAllConfigsOfScenario(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -431,7 +431,7 @@ func TestGetAllConfigsOfScenario(t *testing.T) {
|
|||
newConfig1.ICID = ICID
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newConfig
|
||||
|
@ -448,7 +448,7 @@ func TestGetAllConfigsOfScenario(t *testing.T) {
|
|||
assert.Equal(t, 1, NumberOfConfigs)
|
||||
|
||||
// authenticate as normal userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to get configs without access
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
)
|
||||
|
||||
func RegisterDashboardEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -55,7 +54,7 @@ func RegisterDashboardEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getDashboards(c *gin.Context) {
|
||||
|
||||
ok, sim := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, sim := database.CheckScenarioPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -102,7 +101,7 @@ func addDashboard(c *gin.Context) {
|
|||
newDashboard := req.createDashboard()
|
||||
|
||||
// Check if user is allowed to modify scenario specified in request
|
||||
ok, _ := scenario.CheckPermissions(c, database.Update, "body", int(newDashboard.ScenarioID))
|
||||
ok, _ := database.CheckScenarioPermissions(c, database.Update, "body", int(newDashboard.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -132,11 +131,14 @@ func addDashboard(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateDashboard(c *gin.Context) {
|
||||
|
||||
ok, oldDashboard := CheckPermissions(c, database.Update, "path", -1)
|
||||
ok, oldDashboard_r := database.CheckDashboardPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldDashboard Dashboard
|
||||
oldDashboard.Dashboard = oldDashboard_r
|
||||
|
||||
var req updateDashboardRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
|
@ -174,12 +176,12 @@ func updateDashboard(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getDashboard(c *gin.Context) {
|
||||
|
||||
ok, dab := CheckPermissions(c, database.Read, "path", -1)
|
||||
ok, dab := database.CheckDashboardPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"dashboard": dab.Dashboard})
|
||||
c.JSON(http.StatusOK, gin.H{"dashboard": dab})
|
||||
}
|
||||
|
||||
// deleteDashboard godoc
|
||||
|
@ -196,11 +198,14 @@ func getDashboard(c *gin.Context) {
|
|||
// @Router /dashboards/{dashboardID} [delete]
|
||||
// @Security Bearer
|
||||
func deleteDashboard(c *gin.Context) {
|
||||
ok, dab := CheckPermissions(c, database.Delete, "path", -1)
|
||||
ok, dab_r := database.CheckDashboardPermissions(c, database.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var dab Dashboard
|
||||
dab.Dashboard = dab_r
|
||||
|
||||
err := dab.delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"dashboard": dab.Dashboard})
|
||||
|
|
|
@ -23,7 +23,8 @@ package dashboard
|
|||
|
||||
import (
|
||||
"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/widget"
|
||||
"log"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
|
@ -47,8 +48,8 @@ func (d *Dashboard) ByID(id uint) error {
|
|||
|
||||
func (d *Dashboard) addToScenario() error {
|
||||
db := database.GetDB()
|
||||
var sim scenario.Scenario
|
||||
err := sim.ByID(d.ScenarioID)
|
||||
var sim database.Scenario
|
||||
err := db.Find(&sim, d.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -81,8 +82,8 @@ func (d *Dashboard) update(modifiedDab Dashboard) error {
|
|||
func (d *Dashboard) delete() error {
|
||||
|
||||
db := database.GetDB()
|
||||
var sim scenario.Scenario
|
||||
err := sim.ByID(d.ScenarioID)
|
||||
var sim database.Scenario
|
||||
err := db.Find(&sim, d.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -107,3 +108,35 @@ func (d *Dashboard) delete() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dashboard) Duplicate(scenarioID uint, signalMap map[uint]uint) error {
|
||||
|
||||
var duplicateD Dashboard
|
||||
duplicateD.Grid = d.Grid
|
||||
duplicateD.Name = d.Name
|
||||
duplicateD.ScenarioID = scenarioID
|
||||
duplicateD.Height = d.Height
|
||||
err := duplicateD.addToScenario()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add widgets to duplicated dashboard
|
||||
var widgets []widget.Widget
|
||||
db := database.GetDB()
|
||||
err = db.Order("ID asc").Model(d).Related(&widgets, "Widgets").Error
|
||||
if err != nil {
|
||||
log.Printf("Error getting widgets for dashboard %d: %s", d.ID, err)
|
||||
}
|
||||
for _, w := range widgets {
|
||||
|
||||
err = w.Duplicate(duplicateD.ID, signalMap)
|
||||
if err != nil {
|
||||
log.Printf("error creating duplicate for widget %d: %s", w.ID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/** Dashboard package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD, dabIDSource string, dabIDBody int) (bool, Dashboard) {
|
||||
|
||||
var dab Dashboard
|
||||
|
||||
err := database.ValidateRole(c, database.ModelDashboard, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation failed): %v", err.Error()))
|
||||
return false, dab
|
||||
}
|
||||
|
||||
dabID, err := helper.GetIDOfElement(c, "dashboardID", dabIDSource, dabIDBody)
|
||||
if err != nil {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
err = dab.ByID(uint(dabID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
ok, _ := scenario.CheckPermissions(c, operation, "body", int(dab.ScenarioID))
|
||||
if !ok {
|
||||
return false, dab
|
||||
}
|
||||
|
||||
return true, dab
|
||||
}
|
|
@ -107,10 +107,10 @@ func TestMain(m *testing.M) {
|
|||
func TestAddDashboard(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
scenarioID := addScenario(token)
|
||||
|
@ -166,7 +166,7 @@ func TestAddDashboard(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// try to get dashboard as a user that is not in the scenario (userB)
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// this should fail with unprocessable entity
|
||||
|
@ -187,10 +187,10 @@ func TestAddDashboard(t *testing.T) {
|
|||
func TestUpdateDashboard(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
scenarioID := addScenario(token)
|
||||
|
@ -212,7 +212,7 @@ func TestUpdateDashboard(t *testing.T) {
|
|||
}
|
||||
|
||||
// authenticate as guest user
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to update a dashboard as guest
|
||||
|
@ -223,7 +223,7 @@ func TestUpdateDashboard(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
code, resp, err = helper.TestEndpoint(router, token,
|
||||
|
@ -261,10 +261,10 @@ func TestUpdateDashboard(t *testing.T) {
|
|||
func TestDeleteDashboard(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
scenarioID := addScenario(token)
|
||||
|
@ -281,7 +281,7 @@ func TestDeleteDashboard(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// try to delete a dashboard from a scenario to which the user has no access
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// this should fail with unprocessable entity
|
||||
|
@ -291,7 +291,7 @@ func TestDeleteDashboard(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to delete a dashboard that does not exist; should return a not found error
|
||||
|
@ -327,10 +327,10 @@ func TestDeleteDashboard(t *testing.T) {
|
|||
func TestGetAllDashboardsOfScenario(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
scenarioID := addScenario(token)
|
||||
|
@ -372,7 +372,7 @@ func TestGetAllDashboardsOfScenario(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// try to get all dashboards as a user that does not belong to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// this should fail with unprocessable entity
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"net/http"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
|
@ -54,7 +53,7 @@ func RegisterFileEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getFiles(c *gin.Context) {
|
||||
|
||||
ok, so := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, so := database.CheckScenarioPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ func getFiles(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func addFile(c *gin.Context) {
|
||||
|
||||
ok, so := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, so := database.CheckScenarioPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -142,11 +141,14 @@ func addFile(c *gin.Context) {
|
|||
func getFile(c *gin.Context) {
|
||||
|
||||
// check access
|
||||
ok, f := CheckPermissions(c, database.Read)
|
||||
ok, f_r := database.CheckFilePermissions(c, database.Read)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var f File
|
||||
f.File = f_r
|
||||
|
||||
err := f.download(c)
|
||||
helper.DBError(c, err)
|
||||
}
|
||||
|
@ -175,11 +177,14 @@ func getFile(c *gin.Context) {
|
|||
func updateFile(c *gin.Context) {
|
||||
|
||||
// check access
|
||||
ok, f := CheckPermissions(c, database.Update)
|
||||
ok, f_r := database.CheckFilePermissions(c, database.Update)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var f File
|
||||
f.File = f_r
|
||||
|
||||
// Extract file from PUT request form
|
||||
fileHeader, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
|
@ -209,11 +214,14 @@ func updateFile(c *gin.Context) {
|
|||
func deleteFile(c *gin.Context) {
|
||||
|
||||
// check access
|
||||
ok, f := CheckPermissions(c, database.Delete)
|
||||
ok, f_r := database.CheckFilePermissions(c, database.Delete)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var f File
|
||||
f.File = f_r
|
||||
|
||||
err := f.Delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"file": f.File})
|
||||
|
|
|
@ -36,7 +36,6 @@ import (
|
|||
"time"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
|
@ -140,8 +139,8 @@ func (f *File) Register(fileHeader *multipart.FileHeader, scenarioID uint) error
|
|||
// Create association to scenario
|
||||
db := database.GetDB()
|
||||
|
||||
var so scenario.Scenario
|
||||
err = so.ByID(scenarioID)
|
||||
var so database.Scenario
|
||||
err = db.Find(&so, scenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -219,8 +218,8 @@ func (f *File) Delete() error {
|
|||
db := database.GetDB()
|
||||
|
||||
// remove association between file and scenario
|
||||
var so scenario.Scenario
|
||||
err := so.ByID(f.ScenarioID)
|
||||
var so database.Scenario
|
||||
err := db.Find(&so, f.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -248,3 +247,38 @@ func (f *File) Delete() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *File) Duplicate(scenarioID uint) error {
|
||||
|
||||
var dup File
|
||||
dup.Name = f.Name
|
||||
dup.Key = f.Key
|
||||
dup.Type = f.Type
|
||||
dup.Size = f.Size
|
||||
dup.Date = f.Date
|
||||
dup.ScenarioID = scenarioID
|
||||
dup.FileData = f.FileData
|
||||
dup.ImageHeight = f.ImageHeight
|
||||
dup.ImageWidth = f.ImageWidth
|
||||
|
||||
// file duplicate will point to the same data blob in the DB (SQL or postgres)
|
||||
|
||||
// Add duplicate File object with parameters to DB
|
||||
err := dup.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create association of duplicate file to scenario ID of duplicate file
|
||||
db := database.GetDB()
|
||||
|
||||
var so database.Scenario
|
||||
err = db.Find(&so, scenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Model(&so).Association("Files").Append(&dup).Error
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/** File package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package file
|
||||
|
||||
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/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD) (bool, File) {
|
||||
|
||||
var f File
|
||||
|
||||
err := database.ValidateRole(c, database.ModelFile, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of file failed): %v", err.Error()))
|
||||
return false, f
|
||||
}
|
||||
|
||||
fileID, err := helper.GetIDOfElement(c, "fileID", "path", -1)
|
||||
if err != nil {
|
||||
return false, f
|
||||
}
|
||||
|
||||
err = f.ByID(uint(fileID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, f
|
||||
}
|
||||
|
||||
if operation != database.Read {
|
||||
// check access to scenario only if operation is not Read (=download) of file
|
||||
ok, _ := scenario.CheckPermissions(c, operation, "body", int(f.ScenarioID))
|
||||
if !ok {
|
||||
return false, f
|
||||
}
|
||||
}
|
||||
|
||||
return true, f
|
||||
}
|
|
@ -53,10 +53,10 @@ type ScenarioRequest struct {
|
|||
func addScenario() (scenarioID uint) {
|
||||
|
||||
// authenticate as admin
|
||||
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, _ := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
|
||||
// authenticate as normal user
|
||||
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, _ = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
|
||||
// POST $newScenario
|
||||
newScenario := ScenarioRequest{
|
||||
|
@ -103,14 +103,14 @@ func TestMain(m *testing.M) {
|
|||
func TestAddFile(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// using the respective endpoints of the API
|
||||
scenarioID := addScenario()
|
||||
|
||||
// authenticate as userB who has no access to the elements in the DB
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
emptyBuf := &bytes.Buffer{}
|
||||
|
@ -123,7 +123,7 @@ func TestAddFile(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST without a scenario ID
|
||||
|
@ -189,14 +189,14 @@ func TestUpdateFile(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// using the respective endpoints of the API
|
||||
scenarioID := addScenario()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// create a testfile.txt in local folder
|
||||
|
@ -236,7 +236,7 @@ func TestUpdateFile(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as userB who has no access to the elements in the DB
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
emptyBuf := &bytes.Buffer{}
|
||||
|
@ -249,7 +249,7 @@ func TestUpdateFile(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user C
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT as guest
|
||||
|
@ -261,7 +261,7 @@ func TestUpdateFile(t *testing.T) {
|
|||
|
||||
// Prepare update
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT with empty body
|
||||
|
@ -318,14 +318,14 @@ func TestUpdateFile(t *testing.T) {
|
|||
func TestDeleteFile(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// using the respective endpoints of the API
|
||||
scenarioID := addScenario()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// create a testfile.txt in local folder
|
||||
|
@ -385,7 +385,7 @@ func TestDeleteFile(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as userB who has no access to the elements in the DB
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to DELETE file from scenario to which userB has no access
|
||||
|
@ -396,7 +396,7 @@ func TestDeleteFile(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all files returned for scenario
|
||||
|
@ -412,7 +412,7 @@ func TestDeleteFile(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user C
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to DELETE file of scenario as guest
|
||||
|
@ -423,7 +423,7 @@ func TestDeleteFile(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Delete the added file 1
|
||||
|
@ -450,14 +450,14 @@ func TestGetAllFilesOfScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// using the respective endpoints of the API
|
||||
scenarioID := addScenario()
|
||||
|
||||
// authenticate as userB who has no access to the elements in the DB
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to get all files for scenario to which userB has not access
|
||||
|
@ -468,7 +468,7 @@ func TestGetAllFilesOfScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
//try to get all files with missing scenario ID; should return a bad request error
|
||||
|
|
|
@ -86,7 +86,7 @@ func getICs(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func addIC(c *gin.Context) {
|
||||
|
||||
ok, _ := CheckPermissions(c, database.ModelInfrastructureComponent, database.Create, false)
|
||||
ok, _ := database.CheckICPermissions(c, database.ModelInfrastructureComponent, database.Create, false)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -147,11 +147,14 @@ func addIC(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateIC(c *gin.Context) {
|
||||
|
||||
ok, oldIC := CheckPermissions(c, database.ModelInfrastructureComponent, database.Update, true)
|
||||
ok, oldIC_r := database.CheckICPermissions(c, database.ModelInfrastructureComponent, database.Update, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldIC InfrastructureComponent
|
||||
oldIC.InfrastructureComponent = oldIC_r
|
||||
|
||||
if oldIC.ManagedExternally {
|
||||
helper.BadRequestError(c, "Cannot update externally managed component via API")
|
||||
return
|
||||
|
@ -196,12 +199,12 @@ func updateIC(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getIC(c *gin.Context) {
|
||||
|
||||
ok, s := CheckPermissions(c, database.ModelInfrastructureComponent, database.Read, true)
|
||||
ok, s := database.CheckICPermissions(c, database.ModelInfrastructureComponent, database.Read, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"ic": s.InfrastructureComponent})
|
||||
c.JSON(http.StatusOK, gin.H{"ic": s})
|
||||
}
|
||||
|
||||
// deleteIC godoc
|
||||
|
@ -219,11 +222,14 @@ func getIC(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteIC(c *gin.Context) {
|
||||
|
||||
ok, s := CheckPermissions(c, database.ModelInfrastructureComponent, database.Delete, true)
|
||||
ok, s_r := database.CheckICPermissions(c, database.ModelInfrastructureComponent, database.Delete, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var s InfrastructureComponent
|
||||
s.InfrastructureComponent = s_r
|
||||
|
||||
// Check if IC is managed externally
|
||||
if s.ManagedExternally {
|
||||
// if so: refuse deletion
|
||||
|
@ -258,11 +264,14 @@ func deleteIC(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getConfigsOfIC(c *gin.Context) {
|
||||
|
||||
ok, s := CheckPermissions(c, database.ModelInfrastructureComponent, database.Read, true)
|
||||
ok, s_r := database.CheckICPermissions(c, database.ModelInfrastructureComponent, database.Read, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var s InfrastructureComponent
|
||||
s.InfrastructureComponent = s_r
|
||||
|
||||
// get all associated configurations
|
||||
allConfigs, _, err := s.getConfigs()
|
||||
if !helper.DBError(c, err) {
|
||||
|
@ -287,7 +296,7 @@ func getConfigsOfIC(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func sendActionToIC(c *gin.Context) {
|
||||
|
||||
ok, s := CheckPermissions(c, database.ModelInfrastructureComponentAction, database.Update, true)
|
||||
ok, s := database.CheckICPermissions(c, database.ModelInfrastructureComponentAction, database.Update, true)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/** InfrastructureComponent package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package infrastructure_component
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, modeltype database.ModelName, operation database.CRUD, hasID bool) (bool, InfrastructureComponent) {
|
||||
|
||||
var s InfrastructureComponent
|
||||
|
||||
err := database.ValidateRole(c, modeltype, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of infrastructure component failed): %v", err.Error()))
|
||||
return false, s
|
||||
}
|
||||
|
||||
if hasID {
|
||||
// Get the ID of the infrastructure component from the context
|
||||
ICID, err := helper.GetIDOfElement(c, "ICID", "path", -1)
|
||||
if err != nil {
|
||||
return false, s
|
||||
}
|
||||
|
||||
err = s.ByID(uint(ICID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, s
|
||||
}
|
||||
}
|
||||
|
||||
return true, s
|
||||
}
|
|
@ -148,10 +148,10 @@ func TestMain(m *testing.M) {
|
|||
func TestAddICAsAdmin(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST with non JSON body
|
||||
|
@ -213,10 +213,10 @@ func TestAddICAsAdmin(t *testing.T) {
|
|||
func TestAddICAsUser(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newIC
|
||||
|
@ -232,10 +232,10 @@ func TestAddICAsUser(t *testing.T) {
|
|||
func TestUpdateICAsAdmin(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newIC
|
||||
|
@ -321,10 +321,10 @@ func TestUpdateICAsAdmin(t *testing.T) {
|
|||
func TestUpdateICAsUser(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newIC
|
||||
|
@ -338,7 +338,7 @@ func TestUpdateICAsUser(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test PUT IC
|
||||
|
@ -354,10 +354,10 @@ func TestUpdateICAsUser(t *testing.T) {
|
|||
func TestDeleteICAsAdmin(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newIC
|
||||
|
@ -431,10 +431,10 @@ func TestDeleteICAsAdmin(t *testing.T) {
|
|||
func TestDeleteICAsUser(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newIC
|
||||
|
@ -448,7 +448,7 @@ func TestDeleteICAsUser(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test DELETE ICs
|
||||
|
@ -463,10 +463,10 @@ func TestDeleteICAsUser(t *testing.T) {
|
|||
func TestGetAllICs(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all ICs response for user
|
||||
|
@ -495,7 +495,7 @@ func TestGetAllICs(t *testing.T) {
|
|||
assert.Equal(t, finalNumber, initialNumber+2)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all ICs response again
|
||||
|
@ -509,10 +509,10 @@ func TestGetAllICs(t *testing.T) {
|
|||
func TestGetConfigsOfIC(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newICA
|
||||
|
@ -534,7 +534,7 @@ func TestGetConfigsOfIC(t *testing.T) {
|
|||
assert.Equal(t, 0, numberOfConfigs)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test GET ic/ID/configs
|
||||
|
@ -556,10 +556,10 @@ func TestGetConfigsOfIC(t *testing.T) {
|
|||
func TestSendActionToIC(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST ic/ $newICA
|
||||
|
@ -605,10 +605,10 @@ func TestCreateUpdateViaAMQPRecv(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// fake an IC update message
|
||||
|
@ -679,10 +679,10 @@ func TestDeleteICViaAMQPRecv(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// fake an IC update message
|
||||
|
|
|
@ -151,7 +151,7 @@ func AddTestData(cfg *config.Config, router *gin.Engine) (*bytes.Buffer, error)
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
var Admin = helper.Credentials{
|
||||
var Admin = database.Credentials{
|
||||
Username: adminName,
|
||||
Password: adminPW,
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"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/file"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
@ -57,7 +56,7 @@ func RegisterResultEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getResults(c *gin.Context) {
|
||||
|
||||
ok, sco := scenario.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, sco := database.CheckScenarioPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -103,7 +102,7 @@ func addResult(c *gin.Context) {
|
|||
newResult := req.createResult()
|
||||
|
||||
// Check if user is allowed to modify scenario specified in request
|
||||
ok, _ := scenario.CheckPermissions(c, database.Update, "body", int(newResult.ScenarioID))
|
||||
ok, _ := database.CheckScenarioPermissions(c, database.Update, "body", int(newResult.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -133,11 +132,14 @@ func addResult(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateResult(c *gin.Context) {
|
||||
|
||||
ok, oldResult := checkPermissions(c, database.Update, "path", -1)
|
||||
ok, oldResult_r := database.CheckResultPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldResult Result
|
||||
oldResult.Result = oldResult_r
|
||||
|
||||
var req updateResultRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
|
@ -175,12 +177,12 @@ func updateResult(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getResult(c *gin.Context) {
|
||||
|
||||
ok, result := checkPermissions(c, database.Read, "path", -1)
|
||||
ok, result := database.CheckResultPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"result": result.Result})
|
||||
c.JSON(http.StatusOK, gin.H{"result": result})
|
||||
}
|
||||
|
||||
// deleteResult godoc
|
||||
|
@ -197,13 +199,16 @@ func getResult(c *gin.Context) {
|
|||
// @Router /results/{resultID} [delete]
|
||||
// @Security Bearer
|
||||
func deleteResult(c *gin.Context) {
|
||||
ok, result := checkPermissions(c, database.Delete, "path", -1)
|
||||
ok, result_r := database.CheckResultPermissions(c, database.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var result Result
|
||||
result.Result = result_r
|
||||
|
||||
// Check if user is allowed to modify scenario associated with result
|
||||
ok, _ = scenario.CheckPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
ok, _ = database.CheckScenarioPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -240,13 +245,16 @@ func deleteResult(c *gin.Context) {
|
|||
// @Router /results/{resultID}/file [post]
|
||||
// @Security Bearer
|
||||
func addResultFile(c *gin.Context) {
|
||||
ok, result := checkPermissions(c, database.Update, "path", -1)
|
||||
ok, result_r := database.CheckResultPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var result Result
|
||||
result.Result = result_r
|
||||
|
||||
// Check if user is allowed to modify scenario associated with result
|
||||
ok, sco := scenario.CheckPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
ok, sco := database.CheckScenarioPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -290,18 +298,24 @@ func addResultFile(c *gin.Context) {
|
|||
func deleteResultFile(c *gin.Context) {
|
||||
|
||||
// check access
|
||||
ok, result := checkPermissions(c, database.Update, "path", -1)
|
||||
ok, result_r := database.CheckResultPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ok, f := file.CheckPermissions(c, database.Delete)
|
||||
var result Result
|
||||
result.Result = result_r
|
||||
|
||||
ok, f_r := database.CheckFilePermissions(c, database.Delete)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var f file.File
|
||||
f.File = f_r
|
||||
|
||||
// Check if user is allowed to modify scenario associated with result
|
||||
ok, _ = scenario.CheckPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
ok, _ = database.CheckScenarioPermissions(c, database.Update, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ package result
|
|||
import (
|
||||
"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/scenario"
|
||||
"log"
|
||||
)
|
||||
|
||||
|
@ -50,8 +49,8 @@ func (r *Result) ByID(id uint) error {
|
|||
|
||||
func (r *Result) addToScenario() error {
|
||||
db := database.GetDB()
|
||||
var sco scenario.Scenario
|
||||
err := sco.ByID(r.ScenarioID)
|
||||
var sco database.Scenario
|
||||
err := db.Find(&sco, r.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -84,8 +83,8 @@ func (r *Result) update(modifiedResult Result) error {
|
|||
func (r *Result) delete() error {
|
||||
|
||||
db := database.GetDB()
|
||||
var sco scenario.Scenario
|
||||
err := sco.ByID(r.ScenarioID)
|
||||
var sco database.Scenario
|
||||
err := db.Find(&sco, r.ScenarioID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/** Result package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
package result
|
||||
|
||||
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/scenario"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func checkPermissions(c *gin.Context, operation database.CRUD, resultIDSource string, resultIDBody int) (bool, Result) {
|
||||
|
||||
var result Result
|
||||
|
||||
err := database.ValidateRole(c, database.ModelResult, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation failed): %v", err.Error()))
|
||||
return false, result
|
||||
}
|
||||
|
||||
resultID, err := helper.GetIDOfElement(c, "resultID", resultIDSource, resultIDBody)
|
||||
if err != nil {
|
||||
return false, result
|
||||
}
|
||||
|
||||
err = result.ByID(uint(resultID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, result
|
||||
}
|
||||
|
||||
ok, _ := scenario.CheckPermissions(c, operation, "body", int(result.ScenarioID))
|
||||
if !ok {
|
||||
return false, result
|
||||
}
|
||||
|
||||
return true, result
|
||||
}
|
|
@ -70,10 +70,10 @@ var newResult = ResultRequest{
|
|||
func addScenario() (scenarioID uint) {
|
||||
|
||||
// authenticate as admin
|
||||
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, _ := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
|
||||
// authenticate as normal user
|
||||
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, _ = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
|
||||
// POST $newScenario
|
||||
newScenario := ScenarioRequest{
|
||||
|
@ -123,14 +123,14 @@ func TestGetAllResultsOfScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario
|
||||
scenarioID := addScenario()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newResult
|
||||
|
@ -152,7 +152,7 @@ func TestGetAllResultsOfScenario(t *testing.T) {
|
|||
assert.Equal(t, 1, NumberOfConfigs)
|
||||
|
||||
// authenticate as normal userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to get results without access
|
||||
|
@ -168,7 +168,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario
|
||||
|
@ -178,7 +178,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
newResult.ScenarioID = scenarioID
|
||||
newResult.ConfigSnapshots = confSnapshots
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST with no access
|
||||
|
@ -189,7 +189,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST non JSON body
|
||||
|
@ -234,7 +234,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try to GET the newResult with no access
|
||||
|
@ -259,7 +259,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user who has access to result
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT as guest
|
||||
|
@ -270,7 +270,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT a non JSON body
|
||||
|
@ -300,7 +300,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
newResult.Description = updatedResult.Description
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to DELETE with no access
|
||||
|
@ -311,7 +311,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the results returned for scenario
|
||||
|
@ -341,7 +341,7 @@ func TestAddGetUpdateDeleteResult(t *testing.T) {
|
|||
func TestAddDeleteResultFile(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario
|
||||
|
@ -352,7 +352,7 @@ func TestAddDeleteResultFile(t *testing.T) {
|
|||
newResult.ScenarioID = scenarioID
|
||||
newResult.ConfigSnapshots = confSnapshots
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST newResult
|
||||
|
|
|
@ -22,14 +22,10 @@
|
|||
package scenario
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"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/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RegisterScenarioEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -60,15 +56,15 @@ func getScenarios(c *gin.Context) {
|
|||
|
||||
// ATTENTION: do not use c.GetInt (common.UserIDCtx) since userID is of type uint and not int
|
||||
userID, _ := c.Get(database.UserIDCtx)
|
||||
|
||||
var u user.User
|
||||
err := u.ByID(userID.(uint))
|
||||
db := database.GetDB()
|
||||
var u database.User
|
||||
err := db.Find(&u, userID.(uint)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
// get all scenarios for the user who issues the request
|
||||
db := database.GetDB()
|
||||
|
||||
var scenarios []database.Scenario
|
||||
if u.Role == "Admin" { // Admin can see all scenarios
|
||||
err = db.Order("ID asc").Find(&scenarios).Error
|
||||
|
@ -102,16 +98,16 @@ func getScenarios(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func addScenario(c *gin.Context) {
|
||||
|
||||
ok, _ := CheckPermissions(c, database.Create, "none", -1)
|
||||
ok, _ := database.CheckScenarioPermissions(c, database.Create, "none", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// ATTENTION: do not use c.GetInt (common.UserIDCtx) since userID is of type uint and not int
|
||||
userID, _ := c.Get(database.UserIDCtx)
|
||||
|
||||
var u user.User
|
||||
err := u.ByID(userID.(uint))
|
||||
db := database.GetDB()
|
||||
var u database.User
|
||||
err := db.Find(&u, userID.(uint)).Error
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -138,7 +134,7 @@ func addScenario(c *gin.Context) {
|
|||
}
|
||||
|
||||
// add user to new scenario
|
||||
err = newScenario.addUser(&(u.User))
|
||||
err = newScenario.addUser(&(u))
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -163,11 +159,14 @@ func addScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateScenario(c *gin.Context) {
|
||||
|
||||
ok, oldScenario := CheckPermissions(c, database.Update, "path", -1)
|
||||
ok, oldScenario_r := database.CheckScenarioPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldScenario Scenario
|
||||
oldScenario.Scenario = oldScenario_r
|
||||
|
||||
// Bind the (context) with the updateScenarioRequest struct
|
||||
var req updateScenarioRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
@ -208,13 +207,13 @@ func updateScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, database.Read, "path", -1)
|
||||
ok, so := database.CheckScenarioPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO return list of configIDs, dashboardIDs and userIDs per scenario
|
||||
c.JSON(http.StatusOK, gin.H{"scenario": so.Scenario})
|
||||
c.JSON(http.StatusOK, gin.H{"scenario": so})
|
||||
}
|
||||
|
||||
// deleteScenario godoc
|
||||
|
@ -231,11 +230,14 @@ func getScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, database.Delete, "path", -1)
|
||||
ok, so_r := database.CheckScenarioPermissions(c, database.Delete, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var so Scenario
|
||||
so.Scenario = so_r
|
||||
|
||||
err := so.delete()
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
|
@ -258,11 +260,14 @@ func deleteScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getUsersOfScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, database.Read, "path", -1)
|
||||
ok, so_r := database.CheckScenarioPermissions(c, database.Read, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var so Scenario
|
||||
so.Scenario = so_r
|
||||
|
||||
// Find all users of scenario
|
||||
allUsers, _, err := so.getUsers()
|
||||
if helper.DBError(c, err) {
|
||||
|
@ -287,15 +292,18 @@ func getUsersOfScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func addUserToScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, database.Update, "path", -1)
|
||||
ok, so_r := database.CheckScenarioPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
username := c.Request.URL.Query().Get("username")
|
||||
var so Scenario
|
||||
so.Scenario = so_r
|
||||
|
||||
var u user.User
|
||||
err := u.ByUsername(username)
|
||||
username := c.Request.URL.Query().Get("username")
|
||||
var u database.User
|
||||
db := database.GetDB()
|
||||
err := db.Find(&u, "Username = ?", username).Error
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -305,12 +313,12 @@ func addUserToScenario(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err = so.addUser(&(u.User))
|
||||
err = so.addUser(&(u))
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"user": u.User})
|
||||
c.JSON(http.StatusOK, gin.H{"user": u})
|
||||
}
|
||||
|
||||
// deleteUserFromScenario godoc
|
||||
|
@ -328,15 +336,18 @@ func addUserToScenario(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteUserFromScenario(c *gin.Context) {
|
||||
|
||||
ok, so := CheckPermissions(c, database.Update, "path", -1)
|
||||
ok, so_r := database.CheckScenarioPermissions(c, database.Update, "path", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
username := c.Request.URL.Query().Get("username")
|
||||
var so Scenario
|
||||
so.Scenario = so_r
|
||||
|
||||
var u user.User
|
||||
err := u.ByUsername(username)
|
||||
username := c.Request.URL.Query().Get("username")
|
||||
var u database.User
|
||||
db := database.GetDB()
|
||||
err := db.Find(&u, "Username = ?", username).Error
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -346,5 +357,5 @@ func deleteUserFromScenario(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"user": u.User})
|
||||
c.JSON(http.StatusOK, gin.H{"user": u})
|
||||
}
|
||||
|
|
|
@ -24,8 +24,13 @@ package scenario
|
|||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/user"
|
||||
component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/file"
|
||||
infrastructure_component "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/infrastructure-component"
|
||||
"github.com/jinzhu/gorm"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Scenario struct {
|
||||
|
@ -82,8 +87,8 @@ func (s *Scenario) addUser(u *database.User) error {
|
|||
func (s *Scenario) deleteUser(username string) error {
|
||||
db := database.GetDB()
|
||||
|
||||
var deletedUser user.User
|
||||
err := deletedUser.ByUsername(username)
|
||||
var deletedUser database.User
|
||||
err := db.Find(&deletedUser, "Username = ?", username).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -92,18 +97,18 @@ func (s *Scenario) deleteUser(username string) error {
|
|||
|
||||
if no_users > 1 {
|
||||
// remove user from scenario
|
||||
err = db.Model(s).Association("Users").Delete(&deletedUser.User).Error
|
||||
err = db.Model(s).Association("Users").Delete(&deletedUser).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// remove scenario from user
|
||||
err = db.Model(&deletedUser.User).Association("Scenarios").Delete(s).Error
|
||||
err = db.Model(&deletedUser).Association("Scenarios").Delete(s).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// There is only one associated user
|
||||
var remainingUser user.User
|
||||
var remainingUser database.User
|
||||
err = db.Model(s).Related(&remainingUser, "Users").Error
|
||||
if remainingUser.Username == username {
|
||||
// if the remaining user is the one to be deleted
|
||||
|
@ -152,32 +157,160 @@ func (s *Scenario) delete() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Scenario) checkAccess(userID uint, operation database.CRUD) bool {
|
||||
func (s *Scenario) DuplicateScenarioForUser(user *database.User) <-chan error {
|
||||
errs := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
|
||||
// get all component configs of the scenario
|
||||
db := database.GetDB()
|
||||
var configs []database.ComponentConfiguration
|
||||
err := db.Order("ID asc").Model(s).Related(&configs, "ComponentConfigurations").Error
|
||||
if err != nil {
|
||||
log.Printf("Warning: scenario to duplicate (id=%d) has no component configurations", s.ID)
|
||||
}
|
||||
|
||||
// iterate over component configs to check for ICs to duplicate
|
||||
duplicatedICuuids := make(map[uint]string) // key: original icID; value: UUID of duplicate
|
||||
var externalUUIDs []string // external ICs to wait for
|
||||
for _, config := range configs {
|
||||
icID := config.ICID
|
||||
if duplicatedICuuids[icID] != "" { // this IC was already added
|
||||
continue
|
||||
}
|
||||
|
||||
var ic infrastructure_component.InfrastructureComponent
|
||||
err = ic.ByID(icID)
|
||||
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("Cannot find IC with id %d in DB, will not duplicate for User %s: %s", icID, user.Username, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// create new kubernetes simulator OR use existing IC
|
||||
if ic.Category == "simulator" && ic.Type == "kubernetes" {
|
||||
duplicateUUID, err := ic.RequestICcreateAMQPsimpleManager(user.Username)
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("Duplication of IC (id=%d) unsuccessful, err: %s", icID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
duplicatedICuuids[ic.ID] = duplicateUUID
|
||||
externalUUIDs = append(externalUUIDs, duplicateUUID)
|
||||
} else { // use existing IC
|
||||
duplicatedICuuids[ic.ID] = ""
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
// copy scenario after all new external ICs are in DB
|
||||
icsToWaitFor := len(externalUUIDs)
|
||||
//var duplicatedScenario database.Scenario
|
||||
var timeout = 20 // seconds
|
||||
|
||||
for i := 0; i < timeout; i++ {
|
||||
// duplicate scenario after all duplicated ICs have been found in the DB
|
||||
if icsToWaitFor == 0 {
|
||||
err := s.duplicateScenario(duplicatedICuuids, user)
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("duplicate scenario %v fails with error %v", s.Name, err.Error())
|
||||
}
|
||||
|
||||
close(errs)
|
||||
return
|
||||
} else {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
// check for new ICs with previously created UUIDs
|
||||
for _, uuid := range externalUUIDs {
|
||||
if uuid == "" {
|
||||
continue
|
||||
}
|
||||
log.Printf("Looking for duplicated IC with UUID %s", uuid)
|
||||
var duplicatedIC database.InfrastructureComponent
|
||||
err = db.Find(&duplicatedIC, "UUID = ?", uuid).Error
|
||||
if err != nil {
|
||||
errs <- fmt.Errorf("Error looking up duplicated IC: %s", err)
|
||||
} else {
|
||||
icsToWaitFor--
|
||||
uuid = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errs <- fmt.Errorf("ALERT! Timed out while waiting for IC duplication, scenario not properly duplicated")
|
||||
close(errs)
|
||||
|
||||
}()
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *Scenario) duplicateScenario(icIds map[uint]string, user *database.User) error {
|
||||
|
||||
db := database.GetDB()
|
||||
u := database.User{}
|
||||
|
||||
err := db.Find(&u, userID).Error
|
||||
var duplicateSo Scenario
|
||||
duplicateSo.Name = s.Name + ` ` + user.Username
|
||||
duplicateSo.StartParameters.RawMessage = s.StartParameters.RawMessage
|
||||
err := duplicateSo.save()
|
||||
if err != nil {
|
||||
return false
|
||||
log.Printf("Could not create duplicate of scenario %d", s.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
if u.Role == "Admin" {
|
||||
return true
|
||||
}
|
||||
|
||||
scenarioUser := database.User{}
|
||||
err = db.Order("ID asc").Model(s).Where("ID = ?", userID).Related(&scenarioUser, "Users").Error
|
||||
// associate user to new scenario
|
||||
err = duplicateSo.addUser(user)
|
||||
if err != nil {
|
||||
return false
|
||||
log.Printf("Could not associate User %s to scenario %d", user.Username, duplicateSo.ID)
|
||||
}
|
||||
log.Println("Associated user to duplicated scenario")
|
||||
|
||||
// duplicate files
|
||||
var files []file.File
|
||||
err = db.Order("ID asc").Model(s).Related(&files, "Files").Error
|
||||
if err != nil {
|
||||
log.Printf("error getting files for scenario %d", s.ID)
|
||||
}
|
||||
for _, f := range files {
|
||||
err = f.Duplicate(duplicateSo.ID)
|
||||
if err != nil {
|
||||
log.Print("error creating duplicate file %d: %s", f.ID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !scenarioUser.Active {
|
||||
return false
|
||||
} else if s.IsLocked && operation != database.Read {
|
||||
return false
|
||||
var configs []component_configuration.ComponentConfiguration
|
||||
// map existing signal IDs to duplicated signal IDs for widget duplication
|
||||
signalMap := make(map[uint]uint)
|
||||
err = db.Order("ID asc").Model(s).Related(&configs, "ComponentConfigurations").Error
|
||||
if err == nil {
|
||||
for _, c := range configs {
|
||||
err = c.Duplicate(duplicateSo.ID, icIds, &signalMap)
|
||||
//err = duplicateComponentConfig(&c, duplicateSo, icIds, userName, &signalMap)
|
||||
if err != nil {
|
||||
log.Printf("Error duplicating component config %d: %s", c.ID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
return err
|
||||
}
|
||||
|
||||
var dabs []dashboard.Dashboard
|
||||
err = db.Order("ID asc").Model(s).Related(&dabs, "Dashboards").Error
|
||||
if err != nil {
|
||||
log.Printf("Error getting dashboards for scenario %d: %s", s.ID, err)
|
||||
}
|
||||
|
||||
for _, dab := range dabs {
|
||||
err = dab.Duplicate(duplicateSo.ID, signalMap)
|
||||
if err != nil {
|
||||
log.Printf("Error duplicating dashboard %d: %s", dab.ID, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/** Scenario package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package scenario
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD, scenarioIDsource string, scenarioIDbody int) (bool, Scenario) {
|
||||
|
||||
var so Scenario
|
||||
|
||||
err := database.ValidateRole(c, database.ModelScenario, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of scenario failed): %v", err))
|
||||
return false, so
|
||||
}
|
||||
|
||||
if operation == database.Create || (operation == database.Read && scenarioIDsource == "none") {
|
||||
return true, so
|
||||
}
|
||||
|
||||
scenarioID, err := helper.GetIDOfElement(c, "scenarioID", scenarioIDsource, scenarioIDbody)
|
||||
if err != nil {
|
||||
return false, so
|
||||
}
|
||||
|
||||
userID, _ := c.Get(database.UserIDCtx)
|
||||
|
||||
err = so.ByID(uint(scenarioID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, so
|
||||
}
|
||||
|
||||
if so.checkAccess(userID.(uint), operation) == false {
|
||||
helper.UnprocessableEntityError(c, "Access denied (user has no access or scenario is locked).")
|
||||
return false, so
|
||||
}
|
||||
|
||||
return true, so
|
||||
}
|
|
@ -91,10 +91,10 @@ func TestAddScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST with non JSON body
|
||||
|
@ -147,7 +147,7 @@ func TestAddScenario(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to add scenario as guest user
|
||||
|
@ -158,7 +158,7 @@ func TestAddScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as userB who has no access to the added scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to GET a scenario to which user B has no access
|
||||
|
@ -169,7 +169,7 @@ func TestAddScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as admin user who has no access to everything
|
||||
token, err = helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to GET a scenario that is not created by admin user; should work anyway
|
||||
|
@ -183,10 +183,10 @@ func TestUpdateScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
|
@ -254,7 +254,7 @@ func TestUpdateScenario(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as admin user who has no access to everything
|
||||
token, err = helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// changed locked state of scenario as admin user (should work)
|
||||
|
@ -290,7 +290,7 @@ func TestUpdateScenario(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get the updatedScenario
|
||||
|
@ -316,10 +316,10 @@ func TestGetAllScenariosAsAdmin(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response for admin
|
||||
|
@ -328,7 +328,7 @@ func TestGetAllScenariosAsAdmin(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario1
|
||||
|
@ -338,7 +338,7 @@ func TestGetAllScenariosAsAdmin(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario2
|
||||
|
@ -348,7 +348,7 @@ func TestGetAllScenariosAsAdmin(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as admin
|
||||
token, err = helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response again
|
||||
|
@ -363,10 +363,10 @@ func TestGetAllScenariosAsUser(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response for userB
|
||||
|
@ -381,7 +381,7 @@ func TestGetAllScenariosAsUser(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userA
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario1
|
||||
|
@ -391,7 +391,7 @@ func TestGetAllScenariosAsUser(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all scenarios response again
|
||||
|
@ -406,10 +406,10 @@ func TestDeleteScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
|
@ -429,7 +429,7 @@ func TestDeleteScenario(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to delete scenario as guest
|
||||
|
@ -440,7 +440,7 @@ func TestDeleteScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the scenarios returned for userA
|
||||
|
@ -470,10 +470,10 @@ func TestAddUserToScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
|
@ -487,7 +487,7 @@ func TestAddUserToScenario(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to add new user User_C to scenario as userB
|
||||
|
@ -505,7 +505,7 @@ func TestAddUserToScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
|
@ -522,9 +522,9 @@ func TestAddUserToScenario(t *testing.T) {
|
|||
|
||||
// Compare resp to userB
|
||||
userB := UserRequest{
|
||||
Username: helper.UserB.Username,
|
||||
Mail: helper.UserB.Mail,
|
||||
Role: helper.UserB.Role,
|
||||
Username: database.UserB.Username,
|
||||
Mail: database.UserB.Mail,
|
||||
Role: database.UserB.Role,
|
||||
}
|
||||
err = helper.CompareResponse(resp, helper.KeyModels{"user": userB})
|
||||
assert.NoError(t, err)
|
||||
|
@ -547,10 +547,10 @@ func TestGetAllUsersOfScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
|
@ -564,7 +564,7 @@ func TestGetAllUsersOfScenario(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to get all users of new scenario with userB
|
||||
|
@ -575,7 +575,7 @@ func TestGetAllUsersOfScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
|
@ -597,7 +597,7 @@ func TestGetAllUsersOfScenario(t *testing.T) {
|
|||
assert.Equal(t, finalNumber, initialNumber+1)
|
||||
|
||||
// authenticate as admin
|
||||
token, err = helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// set userB as inactive
|
||||
|
@ -608,7 +608,7 @@ func TestGetAllUsersOfScenario(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count AGAIN the number of all the users returned for newScenario
|
||||
|
@ -622,10 +622,10 @@ func TestRemoveUserFromScenario(t *testing.T) {
|
|||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST scenarios/ $newScenario
|
||||
|
@ -645,7 +645,7 @@ func TestRemoveUserFromScenario(t *testing.T) {
|
|||
assert.Equalf(t, 200, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to delete userC from new scenario
|
||||
|
@ -656,7 +656,7 @@ func TestRemoveUserFromScenario(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the users returned for newScenario
|
||||
|
@ -673,9 +673,9 @@ func TestRemoveUserFromScenario(t *testing.T) {
|
|||
|
||||
// Compare DELETE's response with UserC's data
|
||||
userC := UserRequest{
|
||||
Username: helper.UserC.Username,
|
||||
Mail: helper.UserC.Mail,
|
||||
Role: helper.UserC.Role,
|
||||
Username: database.UserC.Username,
|
||||
Mail: database.UserC.Mail,
|
||||
Role: database.UserC.Role,
|
||||
}
|
||||
err = helper.CompareResponse(resp, helper.KeyModels{"user": userC})
|
||||
assert.NoError(t, err)
|
||||
|
@ -708,3 +708,13 @@ func TestRemoveUserFromScenario(t *testing.T) {
|
|||
assert.Equalf(t, 404, code, "Response body: \n%v\n", resp)
|
||||
|
||||
}
|
||||
|
||||
func TestDuplicateScenarioForUser(t *testing.T) {
|
||||
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// TODO test duplicate scenario for user function here!!
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration"
|
||||
)
|
||||
|
||||
func RegisterSignalEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -55,7 +54,7 @@ func RegisterSignalEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getSignals(c *gin.Context) {
|
||||
|
||||
ok, m := component_configuration.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, m := database.CheckComponentConfigPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -111,13 +110,13 @@ func addSignal(c *gin.Context) {
|
|||
// Create the new signal from the request
|
||||
newSignal := req.createSignal()
|
||||
|
||||
ok, _ := component_configuration.CheckPermissions(c, database.Update, "body", int(newSignal.ConfigID))
|
||||
ok, _ := database.CheckComponentConfigPermissions(c, database.Update, "body", int(newSignal.ConfigID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Add signal to component configuration
|
||||
err := newSignal.addToConfig()
|
||||
err := newSignal.AddToConfig()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"signal": newSignal.Signal})
|
||||
}
|
||||
|
@ -139,11 +138,14 @@ func addSignal(c *gin.Context) {
|
|||
// @Router /signals/{signalID} [put]
|
||||
// @Security Bearer
|
||||
func updateSignal(c *gin.Context) {
|
||||
ok, oldSignal := checkPermissions(c, database.Delete)
|
||||
ok, oldSignal_r := database.CheckSignalPermissions(c, database.Delete)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldSignal Signal
|
||||
oldSignal.Signal = oldSignal_r
|
||||
|
||||
var req updateSignalRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
|
@ -181,12 +183,12 @@ func updateSignal(c *gin.Context) {
|
|||
// @Router /signals/{signalID} [get]
|
||||
// @Security Bearer
|
||||
func getSignal(c *gin.Context) {
|
||||
ok, sig := checkPermissions(c, database.Delete)
|
||||
ok, sig := database.CheckSignalPermissions(c, database.Delete)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"signal": sig.Signal})
|
||||
c.JSON(http.StatusOK, gin.H{"signal": sig})
|
||||
}
|
||||
|
||||
// deleteSignal godoc
|
||||
|
@ -204,11 +206,14 @@ func getSignal(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteSignal(c *gin.Context) {
|
||||
|
||||
ok, sig := checkPermissions(c, database.Delete)
|
||||
ok, sig_r := database.CheckSignalPermissions(c, database.Delete)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var sig Signal
|
||||
sig.Signal = sig_r
|
||||
|
||||
err := sig.delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"signal": sig.Signal})
|
||||
|
|
|
@ -23,7 +23,6 @@ package signal
|
|||
|
||||
import (
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration"
|
||||
)
|
||||
|
||||
type Signal struct {
|
||||
|
@ -45,11 +44,11 @@ func (s *Signal) byID(id uint) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Signal) addToConfig() error {
|
||||
func (s *Signal) AddToConfig() error {
|
||||
db := database.GetDB()
|
||||
var err error
|
||||
var m component_configuration.ComponentConfiguration
|
||||
err = m.ByID(s.ConfigID)
|
||||
var m database.ComponentConfiguration
|
||||
err = db.Find(&m, s.ConfigID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -92,8 +91,8 @@ func (s *Signal) delete() error {
|
|||
|
||||
db := database.GetDB()
|
||||
var err error
|
||||
var m component_configuration.ComponentConfiguration
|
||||
err = m.ByID(s.ConfigID)
|
||||
var m database.ComponentConfiguration
|
||||
err = db.Find(&m, s.ConfigID).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/** Signal package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package signal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration"
|
||||
)
|
||||
|
||||
func checkPermissions(c *gin.Context, operation database.CRUD) (bool, Signal) {
|
||||
|
||||
var sig Signal
|
||||
|
||||
err := database.ValidateRole(c, database.ModelSignal, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of signal failed): %v", err.Error()))
|
||||
return false, sig
|
||||
}
|
||||
|
||||
signalID, err := helper.GetIDOfElement(c, "signalID", "path", -1)
|
||||
if err != nil {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
err = sig.byID(uint(signalID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
ok, _ := component_configuration.CheckPermissions(c, operation, "body", int(sig.ConfigID))
|
||||
if !ok {
|
||||
return false, sig
|
||||
}
|
||||
|
||||
return true, sig
|
||||
}
|
|
@ -91,7 +91,7 @@ func newFalse() *bool {
|
|||
func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) {
|
||||
|
||||
// authenticate as admin
|
||||
token, _ := helper.AuthenticateForTest(router, helper.AdminCredentials)
|
||||
token, _ := helper.AuthenticateForTest(router, database.AdminCredentials)
|
||||
|
||||
// POST $newICA
|
||||
newICA := ICRequest{
|
||||
|
@ -114,7 +114,7 @@ func addScenarioAndICAndConfig() (scenarioID uint, ICID uint, configID uint) {
|
|||
newICID, _ := helper.GetResponseID(resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, _ = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, _ = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
|
||||
// POST $newScenario
|
||||
newScenario := ScenarioRequest{
|
||||
|
@ -181,7 +181,7 @@ func TestMain(m *testing.M) {
|
|||
func TestAddSignal(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -189,12 +189,12 @@ func TestAddSignal(t *testing.T) {
|
|||
_, _, configID := addScenarioAndICAndConfig()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
newSignal1.ConfigID = configID
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST to component config without access
|
||||
|
@ -205,7 +205,7 @@ func TestAddSignal(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST a signal with non JSON body
|
||||
|
@ -251,7 +251,7 @@ func TestAddSignal(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try to Get the newSignal as user B
|
||||
|
@ -265,7 +265,7 @@ func TestAddSignal(t *testing.T) {
|
|||
func TestUpdateSignal(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -273,7 +273,7 @@ func TestUpdateSignal(t *testing.T) {
|
|||
_, _, configID := addScenarioAndICAndConfig()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST signals/ $newSignal
|
||||
|
@ -294,7 +294,7 @@ func TestUpdateSignal(t *testing.T) {
|
|||
}
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT signal without access
|
||||
|
@ -305,7 +305,7 @@ func TestUpdateSignal(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to update signal as guest who has access to scenario
|
||||
|
@ -316,7 +316,7 @@ func TestUpdateSignal(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT with non JSON body
|
||||
|
@ -357,7 +357,7 @@ func TestUpdateSignal(t *testing.T) {
|
|||
func TestDeleteSignal(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -365,7 +365,7 @@ func TestDeleteSignal(t *testing.T) {
|
|||
_, _, configID := addScenarioAndICAndConfig()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// test POST signals/ $newSignal
|
||||
|
@ -386,7 +386,7 @@ func TestDeleteSignal(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try to DELETE signal with no access
|
||||
|
@ -397,7 +397,7 @@ func TestDeleteSignal(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the input signals returned for component config
|
||||
|
@ -443,7 +443,7 @@ func TestDeleteSignal(t *testing.T) {
|
|||
func TestGetAllInputSignalsOfConfig(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// prepare the content of the DB for testing
|
||||
// by adding a scenario and a IC to the DB
|
||||
|
@ -451,7 +451,7 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) {
|
|||
_, _, configID := addScenarioAndICAndConfig()
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the input signals returned for component config
|
||||
|
@ -526,7 +526,7 @@ func TestGetAllInputSignalsOfConfig(t *testing.T) {
|
|||
assert.Equalf(t, 400, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal userB who has no access to new scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to get all input signals
|
||||
|
|
|
@ -23,6 +23,7 @@ package user
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/scenario"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -69,7 +70,7 @@ func authenticated(c *gin.Context) {
|
|||
userID, _ := c.Get(database.UserIDCtx)
|
||||
|
||||
var user User
|
||||
err := user.ByID(userID.(uint))
|
||||
err := user.byID(userID.(uint))
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -205,7 +206,7 @@ func authenticateInternal(c *gin.Context) (User, error) {
|
|||
}
|
||||
|
||||
// Find the username in the database
|
||||
err := myUser.ByUsername(credentials.Username)
|
||||
err := myUser.byUsername(credentials.Username)
|
||||
if err != nil {
|
||||
helper.UnauthorizedError(c, "Unknown username")
|
||||
return myUser, err
|
||||
|
@ -239,7 +240,7 @@ func authenticateExternal(c *gin.Context) (User, error) {
|
|||
// preferred_username := c.Request.Header.Get("X-Forwarded-Preferred-Username")
|
||||
|
||||
// check if user already exists
|
||||
err := myUser.ByUsername(username)
|
||||
err := myUser.byUsername(username)
|
||||
|
||||
if err != nil {
|
||||
// this is the first login, create new user
|
||||
|
@ -262,7 +263,7 @@ func authenticateExternal(c *gin.Context) (User, error) {
|
|||
for _, group := range groups {
|
||||
if groupedArr, ok := configuration.ScenarioGroupMap[group]; ok {
|
||||
for _, groupedScenario := range groupedArr {
|
||||
var so database.Scenario
|
||||
var so scenario.Scenario
|
||||
err := db.Find(&so, groupedScenario.Scenario).Error
|
||||
if err != nil {
|
||||
log.Printf(`Cannot find scenario %s (id=%d) for adding/duplication.
|
||||
|
@ -278,9 +279,11 @@ func authenticateExternal(c *gin.Context) (User, error) {
|
|||
}
|
||||
|
||||
if groupedScenario.Duplicate {
|
||||
if err := <-duplicateScenarioForUser(&so, &myUser.User); err != nil {
|
||||
|
||||
if err := <-so.DuplicateScenarioForUser(&myUser.User); err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
} else { // add user to scenario
|
||||
err = db.Model(&so).Association("Users").Append(&(myUser.User)).Error
|
||||
if err != nil {
|
||||
|
|
|
@ -179,7 +179,7 @@ func updateUser(c *gin.Context) {
|
|||
|
||||
// Find the user
|
||||
var oldUser User
|
||||
err = oldUser.ByID(uint(toBeUpdatedID))
|
||||
err = oldUser.byID(uint(toBeUpdatedID))
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ func getUser(c *gin.Context) {
|
|||
}
|
||||
|
||||
var user User
|
||||
err = user.ByID(uint(id))
|
||||
err = user.byID(uint(id))
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"user": user.User})
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ func deleteUser(c *gin.Context) {
|
|||
}
|
||||
|
||||
// Check that the user exist
|
||||
err = user.ByID(uint(id))
|
||||
err = user.byID(uint(id))
|
||||
if helper.DBError(c, err) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func NewUser(username, password, mail, role string, active bool) (User, error) {
|
|||
var newUser User
|
||||
|
||||
// Check that the username is NOT taken
|
||||
err := newUser.ByUsername(username)
|
||||
err := newUser.byUsername(username)
|
||||
if err == nil {
|
||||
return newUser, fmt.Errorf("Username is already taken")
|
||||
}
|
||||
|
@ -83,13 +83,13 @@ func (u *User) remove() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (u *User) ByUsername(username string) error {
|
||||
func (u *User) byUsername(username string) error {
|
||||
db := database.GetDB()
|
||||
err := db.Find(u, "Username = ?", username).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (u *User) ByID(id uint) error {
|
||||
func (u *User) byID(id uint) error {
|
||||
db := database.GetDB()
|
||||
err := db.Find(u, id).Error
|
||||
return err
|
||||
|
|
|
@ -41,7 +41,7 @@ func claimsToContext(c *gin.Context, claims jwt.MapClaims) error {
|
|||
|
||||
var user User
|
||||
|
||||
err := user.ByID(uint(userID))
|
||||
err := user.byID(uint(userID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ func TestAuthenticate(t *testing.T) {
|
|||
router.ServeHTTP(w1, req)
|
||||
assert.Equalf(t, 401, w1.Code, "Response body: \n%v\n", w1.Body)
|
||||
|
||||
malformedCredentials := helper.Credentials{
|
||||
malformedCredentials := database.Credentials{
|
||||
Username: "TEST1",
|
||||
}
|
||||
// try to authenticate with malformed credentials
|
||||
|
@ -126,7 +126,7 @@ func TestAuthenticate(t *testing.T) {
|
|||
assert.Equal(t, 401, w4.Code, w4.Body)
|
||||
|
||||
// authenticate as admin
|
||||
_, err = helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
_, err = helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func TestUserGroups(t *testing.T) {
|
|||
role := "User"
|
||||
userGroups := strings.Split("testGroup1,testGroup2", ",")
|
||||
|
||||
err := myUser.ByUsername(username)
|
||||
err := myUser.byUsername(username)
|
||||
assert.Error(t, err)
|
||||
myUser, err = NewUser(username, "", email, role, true)
|
||||
assert.NoError(t, err)
|
||||
|
@ -176,7 +176,7 @@ func TestAuthenticateQueryToken(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
@ -197,7 +197,7 @@ func TestAddGetUser(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST with non JSON body
|
||||
|
@ -321,7 +321,7 @@ func TestUsersNotAllowedActions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add a user
|
||||
|
@ -380,7 +380,7 @@ func TestGetAllUsers(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// get the length of the GET all users response
|
||||
|
@ -407,7 +407,7 @@ func TestGetAllUsers(t *testing.T) {
|
|||
|
||||
assert.Equal(t, finalNumber, initialNumber+1)
|
||||
|
||||
newUserCredentials := helper.Credentials{
|
||||
newUserCredentials := database.Credentials{
|
||||
Username: newUser.Username,
|
||||
Password: newUser.Password,
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ func TestModifyAddedUserAsUser(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add a user that will modify itself
|
||||
|
@ -588,7 +588,7 @@ func TestInvalidUserUpdate(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add a user
|
||||
|
@ -661,7 +661,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add a user
|
||||
|
@ -747,7 +747,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err = helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err = helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// modify newUser's Active status
|
||||
|
@ -778,7 +778,7 @@ func TestDeleteUser(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as admin
|
||||
token, err := helper.AuthenticateForTest(router, helper.Credentials{Username: "admin", Password: adminpw})
|
||||
token, err := helper.AuthenticateForTest(router, database.Credentials{Username: "admin", Password: adminpw})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add a user
|
||||
|
|
|
@ -99,7 +99,7 @@ func (r *updateUserRequest) updatedUser(callerID interface{}, role interface{},
|
|||
|
||||
// Update the username making sure it is NOT taken
|
||||
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")
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ func (r *updateUserRequest) updatedUser(callerID interface{}, role interface{},
|
|||
|
||||
if role == "Admin" { // admin has to enter admin password
|
||||
var adminUser User
|
||||
err := adminUser.ByID(callerID.(uint))
|
||||
err := adminUser.byID(callerID.(uint))
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
func RegisterWidgetEndpoints(r *gin.RouterGroup) {
|
||||
|
@ -54,7 +53,7 @@ func RegisterWidgetEndpoints(r *gin.RouterGroup) {
|
|||
// @Security Bearer
|
||||
func getWidgets(c *gin.Context) {
|
||||
|
||||
ok, dab := dashboard.CheckPermissions(c, database.Read, "query", -1)
|
||||
ok, dab := database.CheckDashboardPermissions(c, database.Read, "query", -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ func addWidget(c *gin.Context) {
|
|||
newWidget := req.createWidget()
|
||||
|
||||
// Check if user is allowed to modify selected dashboard (scenario)
|
||||
ok, _ := dashboard.CheckPermissions(c, database.Update, "body", int(newWidget.DashboardID))
|
||||
ok, _ := database.CheckDashboardPermissions(c, database.Update, "body", int(newWidget.DashboardID))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
@ -129,11 +128,14 @@ func addWidget(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func updateWidget(c *gin.Context) {
|
||||
|
||||
ok, oldWidget := CheckPermissions(c, database.Update, -1)
|
||||
ok, oldWidget_r := database.CheckWidgetPermissions(c, database.Update, -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var oldWidget Widget
|
||||
oldWidget.Widget = oldWidget_r
|
||||
|
||||
var req updateWidgetRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.BadRequestError(c, err.Error())
|
||||
|
@ -172,12 +174,12 @@ func updateWidget(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func getWidget(c *gin.Context) {
|
||||
|
||||
ok, w := CheckPermissions(c, database.Read, -1)
|
||||
ok, w := database.CheckWidgetPermissions(c, database.Read, -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"widget": w.Widget})
|
||||
c.JSON(http.StatusOK, gin.H{"widget": w})
|
||||
}
|
||||
|
||||
// deleteWidget godoc
|
||||
|
@ -195,11 +197,14 @@ func getWidget(c *gin.Context) {
|
|||
// @Security Bearer
|
||||
func deleteWidget(c *gin.Context) {
|
||||
|
||||
ok, w := CheckPermissions(c, database.Delete, -1)
|
||||
ok, w_r := database.CheckWidgetPermissions(c, database.Delete, -1)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var w Widget
|
||||
w.Widget = w_r
|
||||
|
||||
err := w.delete()
|
||||
if !helper.DBError(c, err) {
|
||||
c.JSON(http.StatusOK, gin.H{"widget": w.Widget})
|
||||
|
|
|
@ -23,7 +23,6 @@ package widget
|
|||
|
||||
import (
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
type Widget struct {
|
||||
|
@ -47,8 +46,8 @@ func (w *Widget) ByID(id uint) error {
|
|||
|
||||
func (w *Widget) addToDashboard() error {
|
||||
db := database.GetDB()
|
||||
var dab dashboard.Dashboard
|
||||
err := dab.ByID(uint(w.DashboardID))
|
||||
var dab database.Dashboard
|
||||
err := db.Find(&dab, uint(w.DashboardID)).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -89,8 +88,8 @@ func (w *Widget) update(modifiedWidget Widget) error {
|
|||
func (w *Widget) delete() error {
|
||||
|
||||
db := database.GetDB()
|
||||
var dab dashboard.Dashboard
|
||||
err := dab.ByID(w.DashboardID)
|
||||
var dab database.Dashboard
|
||||
err := db.Find(&dab, uint(w.DashboardID)).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -106,3 +105,26 @@ func (w *Widget) delete() error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (w *Widget) Duplicate(dashboardID uint, signalMap map[uint]uint) error {
|
||||
var duplicateW Widget
|
||||
duplicateW.DashboardID = dashboardID
|
||||
duplicateW.CustomProperties = w.CustomProperties
|
||||
duplicateW.Height = w.Height
|
||||
duplicateW.Width = w.Width
|
||||
duplicateW.MinHeight = w.MinHeight
|
||||
duplicateW.MinWidth = w.MinWidth
|
||||
duplicateW.Name = w.Name
|
||||
duplicateW.Type = w.Type
|
||||
duplicateW.X = w.X
|
||||
duplicateW.Y = w.Y
|
||||
duplicateW.Z = w.Z
|
||||
|
||||
duplicateW.SignalIDs = []int64{}
|
||||
for _, id := range w.SignalIDs {
|
||||
duplicateW.SignalIDs = append(duplicateW.SignalIDs, int64(signalMap[uint(id)]))
|
||||
}
|
||||
|
||||
err := duplicateW.addToDashboard()
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/** Widget package, middleware.
|
||||
*
|
||||
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASweb-backend-go
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
package widget
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/helper"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
|
||||
"git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/dashboard"
|
||||
)
|
||||
|
||||
func CheckPermissions(c *gin.Context, operation database.CRUD, widgetIDBody int) (bool, Widget) {
|
||||
|
||||
var w Widget
|
||||
var err error
|
||||
err = database.ValidateRole(c, database.ModelWidget, operation)
|
||||
if err != nil {
|
||||
helper.UnprocessableEntityError(c, fmt.Sprintf("Access denied (role validation of widget failed): %v", err.Error()))
|
||||
return false, w
|
||||
}
|
||||
|
||||
var widgetID int
|
||||
if widgetIDBody < 0 {
|
||||
widgetID, err = helper.GetIDOfElement(c, "widgetID", "path", -1)
|
||||
if err != nil {
|
||||
return false, w
|
||||
}
|
||||
} else {
|
||||
widgetID = widgetIDBody
|
||||
}
|
||||
|
||||
err = w.ByID(uint(widgetID))
|
||||
if helper.DBError(c, err) {
|
||||
return false, w
|
||||
}
|
||||
|
||||
ok, _ := dashboard.CheckPermissions(c, operation, "body", int(w.DashboardID))
|
||||
if !ok {
|
||||
return false, w
|
||||
}
|
||||
|
||||
return true, w
|
||||
}
|
|
@ -145,17 +145,17 @@ func TestMain(m *testing.M) {
|
|||
func TestAddWidget(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, dashboardID := addScenarioAndDashboard(token)
|
||||
|
||||
newWidget.DashboardID = dashboardID
|
||||
// authenticate as userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST the newWidget with no access to the scenario
|
||||
|
@ -166,7 +166,7 @@ func TestAddWidget(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to POST non JSON body
|
||||
|
@ -212,7 +212,7 @@ func TestAddWidget(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to GET the newWidget with no access to the scenario
|
||||
|
@ -226,10 +226,10 @@ func TestAddWidget(t *testing.T) {
|
|||
func TestUpdateWidget(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, dashboardID := addScenarioAndDashboard(token)
|
||||
|
@ -257,7 +257,7 @@ func TestUpdateWidget(t *testing.T) {
|
|||
}
|
||||
|
||||
// authenticate as userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT the updatedWidget with no access to the scenario
|
||||
|
@ -268,7 +268,7 @@ func TestUpdateWidget(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as guest user who has access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.GuestCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.GuestCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT as guest
|
||||
|
@ -279,7 +279,7 @@ func TestUpdateWidget(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to PUT non JSON body
|
||||
|
@ -320,10 +320,10 @@ func TestUpdateWidget(t *testing.T) {
|
|||
func TestDeleteWidget(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, dashboardID := addScenarioAndDashboard(token)
|
||||
|
@ -340,7 +340,7 @@ func TestDeleteWidget(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// authenticate as userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to DELETE the newWidget with no access to the scenario
|
||||
|
@ -351,7 +351,7 @@ func TestDeleteWidget(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the widgets returned for dashboard
|
||||
|
@ -380,16 +380,16 @@ func TestDeleteWidget(t *testing.T) {
|
|||
func TestGetAllWidgetsOfDashboard(t *testing.T) {
|
||||
database.DropTables()
|
||||
database.MigrateModels()
|
||||
assert.NoError(t, helper.AddTestUsers())
|
||||
assert.NoError(t, database.AddTestUsers())
|
||||
|
||||
// authenticate as normal user
|
||||
token, err := helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err := helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, dashboardID := addScenarioAndDashboard(token)
|
||||
|
||||
// authenticate as userB who has no access to scenario
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserBCredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserBCredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// try to GET all widgets of dashboard
|
||||
|
@ -400,7 +400,7 @@ func TestGetAllWidgetsOfDashboard(t *testing.T) {
|
|||
assert.Equalf(t, 422, code, "Response body: \n%v\n", resp)
|
||||
|
||||
// authenticate as normal user
|
||||
token, err = helper.AuthenticateForTest(router, helper.UserACredentials)
|
||||
token, err = helper.AuthenticateForTest(router, database.UserACredentials)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Count the number of all the widgets returned for dashboard
|
||||
|
|
Loading…
Add table
Reference in a new issue