Merge branch 'master' into test-user-endpoints

This commit is contained in:
smavros 2019-08-30 15:47:54 +02:00
commit f4a15e914e
5 changed files with 181 additions and 57 deletions

View file

@ -3,7 +3,6 @@ package common
import ( import (
"time" "time"
"github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres" "github.com/jinzhu/gorm/dialects/postgres"
) )
@ -33,62 +32,62 @@ type User struct {
// Scenario data model // Scenario data model
type Scenario struct { type Scenario struct {
gorm.Model Model
// Name of scenario // Name of scenario
Name string `gorm:"not null"` Name string `gorm:"not null",json:"name"`
// Running state of scenario // Running state of scenario
Running bool `gorm:"default:false"` Running bool `gorm:"default:false",json:"running"`
// Start parameters of scenario as JSON // Start parameters of scenario as JSON
StartParameters postgres.Jsonb StartParameters postgres.Jsonb `json:"startParameters"`
// Users that have access to the scenario // Users that have access to the scenario
Users []*User `gorm:"not null;many2many:user_scenarios"` Users []*User `gorm:"not null;many2many:user_scenarios",json:"-"`
// SimulationModels that belong to the scenario // SimulationModels that belong to the scenario
SimulationModels []SimulationModel `gorm:"foreignkey:ScenarioID"` SimulationModels []SimulationModel `gorm:"foreignkey:ScenarioID",json:"-"`
// Dashboards that belong to the Scenario // Dashboards that belong to the Scenario
Dashboards []Dashboard `gorm:"foreignkey:ScenarioID"` Dashboards []Dashboard `gorm:"foreignkey:ScenarioID",json:"-"`
} }
// SimulationModel data model // SimulationModel data model
type SimulationModel struct { type SimulationModel struct {
gorm.Model Model
// Name of simulation model // Name of simulation model
Name string `gorm:"not null"` Name string `gorm:"not null",json:"name"`
// Number of output signals // Number of output signals
OutputLength int `gorm:"default:1"` OutputLength int `gorm:"default:1",json:"outputLength"`
// Number of input signals // Number of input signals
InputLength int `gorm:"default:1"` InputLength int `gorm:"default:1",json:"inputLength"`
// Start parameters of simulation model as JSON // Start parameters of simulation model as JSON
StartParameters postgres.Jsonb StartParameters postgres.Jsonb `json:"startParameters"`
// ID of Scenario to which simulation model belongs // ID of Scenario to which simulation model belongs
ScenarioID uint ScenarioID uint `json:"scenarioID"`
// ID of simulator associated with simulation model // ID of simulator associated with simulation model
SimulatorID uint SimulatorID uint `json:"simulatorID"`
// Mapping of output signals of the simulation model, order of signals is important // Mapping of output signals of the simulation model, order of signals is important
OutputMapping []Signal `gorm:"foreignkey:SimulationModelID"` OutputMapping []Signal `gorm:"foreignkey:SimulationModelID",json:"-"`
// Mapping of input signals of the simulation model, order of signals is important // Mapping of input signals of the simulation model, order of signals is important
InputMapping []Signal `gorm:"foreignkey:SimulationModelID"` InputMapping []Signal `gorm:"foreignkey:SimulationModelID",json:"-"`
// Files of simulation model (can be CIM and other simulation model file formats) // Files of simulation model (can be CIM and other simulation model file formats)
Files []File `gorm:"foreignkey:SimulationModelID"` Files []File `gorm:"foreignkey:SimulationModelID",json:"-"`
} }
// Signal data model // Signal data model
type Signal struct { type Signal struct {
gorm.Model Model
// Name of Signal // Name of Signal
Name string Name string `json:"name"`
// Unit of Signal // Unit of Signal
Unit string Unit string `json:"unit"`
// Index of the Signal in the mapping // Index of the Signal in the mapping
Index uint Index uint `json:"index"`
// Direction of the signal (in or out) // Direction of the signal (in or out)
Direction string Direction string `json:"direction"`
// ID of simulation model // ID of simulation model
SimulationModelID uint SimulationModelID uint `json:"simulationModelID"`
} }
// Simulator data model // Simulator data model
type Simulator struct { type Simulator struct {
gorm.Model Model
// UUID of the simulator // UUID of the simulator
UUID string `gorm:"not null",json:"uuid"` UUID string `gorm:"not null",json:"uuid"`
// Host if the simulator // Host if the simulator
@ -106,72 +105,72 @@ type Simulator struct {
// Raw properties of simulator as JSON string // Raw properties of simulator as JSON string
RawProperties postgres.Jsonb `json:"rawProperties"` RawProperties postgres.Jsonb `json:"rawProperties"`
// SimulationModels in which the simulator is used // SimulationModels in which the simulator is used
SimulationModels []SimulationModel `gorm:"foreignkey:SimulatorID"` SimulationModels []SimulationModel `gorm:"foreignkey:SimulatorID",json:"-"`
} }
// Dashboard data model // Dashboard data model
type Dashboard struct { type Dashboard struct {
gorm.Model Model
// Name of dashboard // Name of dashboard
Name string `gorm:"not null"` Name string `gorm:"not null",json:"name"`
// Grid of dashboard // Grid of dashboard
Grid int `gorm:"default:15"` Grid int `gorm:"default:15",json:"grid"`
// ID of scenario to which dashboard belongs // ID of scenario to which dashboard belongs
ScenarioID uint ScenarioID uint `json:"scenarioID"`
// Widgets that belong to dashboard // Widgets that belong to dashboard
Widgets []Widget `gorm:"foreignkey:DashboardID"` Widgets []Widget `gorm:"foreignkey:DashboardID",json:"-"`
} }
// Widget data model // Widget data model
type Widget struct { type Widget struct {
gorm.Model Model
// Name of widget // Name of widget
Name string `gorm:"not null"` Name string `gorm:"not null",json:"name"`
// Type of widget // Type of widget
Type string `gorm:"not null"` Type string `gorm:"not null",json:"type"`
// Width of widget // Width of widget
Width uint `gorm:"not null"` Width uint `gorm:"not null",json:"width"`
// Height of widget // Height of widget
Height uint `gorm:"not null"` Height uint `gorm:"not null",json:"height"`
// Minimal width of widget // Minimal width of widget
MinWidth uint `gorm:"not null"` MinWidth uint `gorm:"not null",json:"minWidth"`
// Minimal height of widget // Minimal height of widget
MinHeight uint `gorm:"not null"` MinHeight uint `gorm:"not null",json:"minHeight"`
// X position of widget // X position of widget
X int `gorm:"not null"` X int `gorm:"not null",json:"x"`
// Y position of widget // Y position of widget
Y int `gorm:"not null"` Y int `gorm:"not null",json:"y"`
// Z position of widget // Z position of widget
Z int `gorm:"not null"` Z int `gorm:"not null",json:"z"`
// Locked state of widget // Locked state of widget
IsLocked bool `gorm:"default:false"` IsLocked bool `gorm:"default:false",json:"isLocked"`
// Custom properties of widget as JSON string // Custom properties of widget as JSON string
CustomProperties postgres.Jsonb CustomProperties postgres.Jsonb `json:"customProperties"`
// ID of dashboard to which widget belongs // ID of dashboard to which widget belongs
DashboardID uint DashboardID uint `json:"dashboardID"`
// Files that belong to widget (for example images) // Files that belong to widget (for example images)
Files []File `gorm:"foreignkey:WidgetID"` Files []File `gorm:"foreignkey:WidgetID",json:"-"`
} }
// File data model // File data model
type File struct { type File struct {
gorm.Model Model
// Name of file // Name of file
Name string `gorm:"not null"` Name string `gorm:"not null",json:"name"`
// Type of file (MIME type) // Type of file (MIME type)
Type string Type string `json:"type"`
// Size of file (in byte) // Size of file (in byte)
Size uint Size uint `json:"size"`
// Height of image (only needed in case of image) // Height of image (only needed in case of image)
ImageHeight uint ImageHeight uint `json:"imageHeight"`
// Width of image (only needed in case of image) // Width of image (only needed in case of image)
ImageWidth uint ImageWidth uint `json:"imageWidth"`
// Last modification time of file // Last modification time of file
Date string Date string `json:"date"`
// ID of model to which file belongs // ID of model to which file belongs
SimulationModelID uint SimulationModelID uint `json:"simulationModelID"`
// ID of widget to which file belongs // ID of widget to which file belongs
WidgetID uint WidgetID uint `json:"widgetID"`
// File itself // File itself
FileData []byte `gorm:"column:FileData"` FileData []byte `gorm:"column:FileData",json:"-"`
} }

View file

@ -15,6 +15,7 @@ import (
type ModelName string type ModelName string
const ModelUser = ModelName("user") const ModelUser = ModelName("user")
const ModelUsers = ModelName("users")
const ModelScenario = ModelName("scenario") const ModelScenario = ModelName("scenario")
const ModelSimulator = ModelName("simulator") const ModelSimulator = ModelName("simulator")
const ModelSimulatorAction = ModelName("simulatoraction") const ModelSimulatorAction = ModelName("simulatoraction")
@ -45,12 +46,14 @@ var crud = Permission{Create: true, Read: true, Update: true, Delete: true}
var _ru_ = Permission{Create: false, Read: true, Update: true, Delete: false} var _ru_ = Permission{Create: false, Read: true, Update: true, Delete: false}
var __u_ = Permission{Create: false, Read: false, Update: true, Delete: false} var __u_ = Permission{Create: false, Read: false, Update: true, Delete: false}
var _r__ = Permission{Create: false, Read: true, Update: false, Delete: false} var _r__ = Permission{Create: false, Read: true, Update: false, Delete: false}
var none = Permission{Create: false, Read: false, Update: false, Delete: false}
// Roles is used as a look up variable to determine if a certain user is // Roles is used as a look up variable to determine if a certain user is
// allowed to do a certain action on a given model based on his role // allowed to do a certain action on a given model based on his role
var Roles = RoleActions{ var Roles = RoleActions{
"Admin": { "Admin": {
ModelUser: crud, ModelUser: crud,
ModelUsers: crud,
ModelScenario: crud, ModelScenario: crud,
ModelSimulationModel: crud, ModelSimulationModel: crud,
ModelSimulator: crud, ModelSimulator: crud,
@ -61,7 +64,8 @@ var Roles = RoleActions{
ModelFile: crud, ModelFile: crud,
}, },
"User": { "User": {
ModelUser: __u_, ModelUser: _ru_,
ModelUsers: none,
ModelScenario: crud, ModelScenario: crud,
ModelSimulationModel: crud, ModelSimulationModel: crud,
ModelSimulator: _r__, ModelSimulator: _r__,
@ -79,6 +83,7 @@ var Roles = RoleActions{
ModelSimulator: _r__, ModelSimulator: _r__,
ModelSimulatorAction: _r__, ModelSimulatorAction: _r__,
ModelUser: _ru_, ModelUser: _ru_,
ModelUsers: none,
ModelSignal: _r__, ModelSignal: _r__,
ModelFile: _r__, ModelFile: _r__,
}, },

109
curl_villasAPI.sh Executable file
View file

@ -0,0 +1,109 @@
#!/bin/bash
# Author: Stefanos Mavros 2019
#
# Handy bash script using curl for testing the checkpoint of the
# VILLASweb frontend. See at the end of the file for usage cases
port='4000'
version='v2'
apiBase='localhost:'"$port"'/api/'"$version"
login () {
printf "> POST "$apiBase"/authenticate\n"
curl "$apiBase"/authenticate -s \
-H "Contet-Type: application/json" \
-X POST \
--data "$1" | jq -r '.token' > auth.jwt \
&& printf '\n'
}
create_user () {
printf "> POST "$apiBase"/users to create newUser\n"
curl "$apiBase"/users -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X POST \
--data "$1" | jq -r '.' && printf '\n'
}
read_users () {
printf "> GET "$apiBase"/users\n"
curl "$apiBase"/users -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X GET | jq '.' && printf '\n'
}
read_simulators () {
printf "> GET "$apiBase"/simulators\n"
curl "$apiBase"/simulators -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X GET | jq '.' && printf '\n'
}
read_user () {
printf "> GET "$apiBase"/users/$1\n"
curl "$apiBase"/users/$1 -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X GET | jq '.' && printf '\n'
}
update_user () {
printf "> PUT "$apiBase"/users to update newUser\n"
curl "$apiBase"/users/$1 -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X PUT \
--data "$2" | jq -r '.' && printf '\n'
}
delete_user () {
printf "> DELETE "$apiBase"/users/$1\n"
curl "$apiBase"/users/$1 -s \
-H "Contet-Type: application/json" \
-H "Authorization: Bearer $(< auth.jwt)" \
-X DELETE | jq '.' && printf '\n'
}
admin='{ "Username" : "User_0",
"Password" : "xyz789",
"Role" : "Admin" }'
userA='{ "Username" : "User_A",
"Password" : "abc123",
"Mail" : "m@i.l" }'
newUserW='{ "user": { "Username" : "User_W",
"Password" : "www747_tst",
"Role" : "User",
"Mail" : "m@i.l" } }'
updUserW='{ "user": { "Mail" : "lalala",
"Role" : "Admin" } }'
#updUserW='{ "user": { "Username" : "User_Wupdated",
#"Password" : "pie314_test",
#"Role" : "Admin",
#"Mail" : "NEW_m@i.l" } }'
userC='{ "user": { "Username" : "User_C",
"Password" : "abc123",
"Mail" : "C_m@i.l",
"Role" : "User"} }'
login "$admin"
#create_user "$userC"
#read_users
#read_user 1
#read_simulators
create_user "$newUserW"
#read_users
read_user 4
#login "$newUserW"
update_user 4 "$updUserW"
#login "$admin"
read_user 4
#login "$admin"
#read_user 4
#login "$updUserW"
#delete_user 2

View file

@ -139,7 +139,7 @@ func authenticate(c *gin.Context) {
// @Router /users [get] // @Router /users [get]
func getUsers(c *gin.Context) { func getUsers(c *gin.Context) {
err := common.ValidateRole(c, common.ModelUser, common.Read) err := common.ValidateRole(c, common.ModelUsers, common.Read)
if err != nil { if err != nil {
c.JSON(http.StatusUnprocessableEntity, fmt.Sprintf("%v", err)) c.JSON(http.StatusUnprocessableEntity, fmt.Sprintf("%v", err))
return return
@ -368,6 +368,17 @@ func getUser(c *gin.Context) {
return return
} }
reqUserID, _ := c.Get(common.UserIDCtx)
reqUserRole, _ := c.Get(common.UserRoleCtx)
if id != reqUserID && reqUserRole != "Admin" {
c.JSON(http.StatusForbidden, gin.H{
"success": false,
"message": "Invalid authorization",
})
return
}
var user User var user User
err = user.ByID(id) err = user.ByID(id)
if err != nil { if err != nil {