diff --git a/database/models.go b/database/models.go index f3bd53d..5e8f4d1 100644 --- a/database/models.go +++ b/database/models.go @@ -26,6 +26,8 @@ type User struct { Mail string `json:"mail" gorm:"default:''"` // Role of user Role string `json:"role" gorm:"default:'user'"` + // Indicating status of user (false means user is inactive and should not be able to login) + Active bool `json:"active" gorm:"default:true"` // Scenarios to which user has access Scenarios []*Scenario `json:"-" gorm:"many2many:user_scenarios;"` } diff --git a/database/testdata.go b/database/testdata.go index 43442f9..34712cb 100644 --- a/database/testdata.go +++ b/database/testdata.go @@ -26,13 +26,13 @@ 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"} + Role: "Admin", Mail: "User_0@example.com", Active: true} var UserA = User{Username: "User_A", Password: string(pwA), - Role: "User", Mail: "User_A@example.com"} + 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"} + 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"} + Role: "Guest", Mail: "User_C@example.com", Active: true} // Simulators diff --git a/go.mod b/go.mod index 8492bcc..e93f033 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect github.com/jinzhu/gorm v1.9.10 - github.com/kr/pty v1.1.8 // indirect github.com/leodido/go-urn v1.1.0 // indirect github.com/mailru/easyjson v0.7.0 // indirect github.com/nsf/jsondiff v0.0.0-20190712045011-8443391ee9b6 @@ -18,10 +17,8 @@ require ( github.com/swaggo/gin-swagger v1.2.0 github.com/swaggo/swag v1.6.2 github.com/tidwall/gjson v1.3.0 - github.com/urfave/cli v1.22.1 // indirect golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 // indirect - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7 // indirect golang.org/x/tools v0.0.0-20190916034716-92af9d69eff2 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect diff --git a/go.sum b/go.sum index 31c4763..8b79982 100644 --- a/go.sum +++ b/go.sum @@ -19,9 +19,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -63,15 +60,11 @@ github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+j github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4= github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2 h1:SStNd1jRcYtfKCN7R0laGNs80WYYvn5CbBjM2sOmCrE= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.3 h1:FKTmP0GPWwRqRP2WIYltgctgYTN+gr8iZ7zSKdZtbz0= -github.com/go-openapi/swag v0.19.3/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= @@ -118,7 +111,6 @@ github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= @@ -164,10 +156,6 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -177,12 +165,11 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/swaggo/gin-swagger v1.2.0 h1:YskZXEiv51fjOMTsXrOetAjrMDfFaXD79PEoQBOe2W0= github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI= github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y= -github.com/swaggo/swag v1.6.0 h1:d6Z3kNGQmM2Z6DZtOyK138eFTkpi2JwSwNVOV4wnlLk= -github.com/swaggo/swag v1.6.0/go.mod h1:YyZstMc22WYm6GEDx/CYWxq+faBbjQ5EqwQcrjREDBo= github.com/swaggo/swag v1.6.2 h1:WQMAtT/FmMBb7g0rAuHDhG3vvdtHKJ3WZ+Ssb0p4Y6E= github.com/swaggo/swag v1.6.2/go.mod h1:YyZstMc22WYm6GEDx/CYWxq+faBbjQ5EqwQcrjREDBo= github.com/tidwall/gjson v1.3.0 h1:kfpsw1W3trbg4Xm6doUtqSl9+LhLB6qJ9PkltVAQZYs= @@ -199,15 +186,11 @@ github.com/ugorji/go/codec v1.1.5-pre h1:5YV9PsFAN+ndcCtTM7s60no7nY7eTG3LPtxhSwu github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -230,8 +213,6 @@ golang.org/x/net v0.0.0-20190611141213-3f473d35a33a h1:+KkCgOMgnKSgenxTBoiwkMqTi golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -242,7 +223,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -255,8 +235,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae h1:xiXzMMEQdQcric9hXtr1QU98MHunKK7OTtsoU6bYWs4= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7 h1:wYqz/tQaWUgGKyx+B/rssSE6wkIKdY5Ee6ryOmzarIg= golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -273,8 +251,6 @@ golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b h1:/mJ+GKieZA6hFDQGdWZrjj4AXPl5ylY+5HusG80roy0= golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190703212419-2214986f1668 h1:3LJOYcj2ObWSZJXX21oGIIPv5SaOoi5JkzQTWnCXRhg= -golang.org/x/tools v0.0.0-20190703212419-2214986f1668/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190916034716-92af9d69eff2 h1:cvSBP3q8DeS4up5q8ssbGdEtSGiDgRV7HBvOpr3g5RM= golang.org/x/tools v0.0.0-20190916034716-92af9d69eff2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -291,6 +267,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= diff --git a/routes/scenario/scenario_endpoints.go b/routes/scenario/scenario_endpoints.go index 9acb3bc..81de207 100644 --- a/routes/scenario/scenario_endpoints.go +++ b/routes/scenario/scenario_endpoints.go @@ -270,6 +270,11 @@ func addUserToScenario(c *gin.Context) { return } + if !u.Active { + helper.BadRequestError(c, "bad user") + return + } + err = so.addUser(&(u.User)) if helper.DBError(c, err) { return diff --git a/routes/scenario/scenario_methods.go b/routes/scenario/scenario_methods.go index d7abe16..ae04b50 100644 --- a/routes/scenario/scenario_methods.go +++ b/routes/scenario/scenario_methods.go @@ -23,7 +23,7 @@ func (s *Scenario) ByID(id uint) error { func (s *Scenario) getUsers() ([]database.User, int, error) { db := database.GetDB() var users []database.User - err := db.Order("ID asc").Model(s).Related(&users, "Users").Error + err := db.Order("ID asc").Model(s).Where("Active = ?", true).Related(&users, "Users").Error return users, len(users), err } @@ -137,7 +137,7 @@ func (s *Scenario) checkAccess(userID uint, userRole string) bool { u := database.User{} u.Username = "" err := db.Order("ID asc").Model(s).Where("ID = ?", userID).Related(&u, "Users").Error - if err != nil { + if err != nil || !u.Active { return false } else { return true diff --git a/routes/scenario/scenario_test.go b/routes/scenario/scenario_test.go index cd83d94..f3b41bc 100644 --- a/routes/scenario/scenario_test.go +++ b/routes/scenario/scenario_test.go @@ -477,6 +477,8 @@ func TestAddUserToScenario(t *testing.T) { fmt.Sprintf("/api/scenarios/%v/user?username=User_D", newScenarioID), "PUT", nil) assert.NoError(t, err) assert.Equalf(t, 404, code, "Response body: \n%v\n", resp) + + // TODO add test for adding an inactive user to a scenario (should fail) } func TestGetAllUsersOfScenario(t *testing.T) { @@ -539,6 +541,8 @@ func TestGetAllUsersOfScenario(t *testing.T) { fmt.Sprintf("/api/scenarios/%v/users", newScenarioID), "GET", nil) assert.NoError(t, err) assert.Equal(t, finalNumber, initialNumber+1) + + // TODO add test where scenario contains active and inactive users, get all users should only give active users } func TestRemoveUserFromScenario(t *testing.T) { diff --git a/routes/user/authenticate_endpoint.go b/routes/user/authenticate_endpoint.go index 9ccb69c..3fa67cb 100644 --- a/routes/user/authenticate_endpoint.go +++ b/routes/user/authenticate_endpoint.go @@ -52,6 +52,12 @@ func authenticate(c *gin.Context) { return } + // Check if this is an active user + if !user.Active { + helper.UnauthorizedError(c, "Wrong username or password") + return + } + // Validate the password err = user.validatePassword(credentials.Password) if err != nil { diff --git a/routes/user/user_endpoints.go b/routes/user/user_endpoints.go index cd04d8e..f88869d 100644 --- a/routes/user/user_endpoints.go +++ b/routes/user/user_endpoints.go @@ -146,7 +146,7 @@ func updateUser(c *gin.Context) { // is illegal // 2: If the udpate is done by the Admin every field can be updated // 3: If the update is done by a User everything can be updated - // except Role + // except Role and Active state // Get caller's ID from context callerID, _ := c.Get(database.UserIDCtx) diff --git a/routes/user/user_methods.go b/routes/user/user_methods.go index f00f864..f95f03d 100644 --- a/routes/user/user_methods.go +++ b/routes/user/user_methods.go @@ -60,13 +60,17 @@ func (u *User) validatePassword(password string) error { func (u *User) update(updatedUser User) error { - // TODO: if the field is empty string member shouldn't be updated u.Username = updatedUser.Username u.Password = updatedUser.Password u.Mail = updatedUser.Mail u.Role = updatedUser.Role + u.Active = updatedUser.Active db := database.GetDB() err := db.Model(u).Update(updatedUser).Error + + // extra update for bool active since it is ignored if false + err = db.Model(u).Updates(map[string]interface{}{"Active": updatedUser.Active}).Error + return err } diff --git a/routes/user/user_test.go b/routes/user/user_test.go index f89aac6..3ec4b76 100644 --- a/routes/user/user_test.go +++ b/routes/user/user_test.go @@ -25,6 +25,7 @@ type UserRequest struct { Password string `json:"password,omitempty"` Mail string `json:"mail,omitempty"` Role string `json:"role,omitempty"` + Active bool `json:"active,omitempty"` } func TestMain(m *testing.M) { @@ -388,8 +389,16 @@ func TestModifyAddedUserAsUser(t *testing.T) { // request-response comparison newUser.Password = "" + // try to modify active state of user + // should result in forbidden + modActiveState := UserRequest{Active: false} + code, resp, err = helper.TestEndpoint(router, token, + fmt.Sprintf("/api/users/%v", newUserID), "PUT", helper.KeyModels{"user": modActiveState}) + assert.NoError(t, err) + assert.Equalf(t, 403, code, "Response body: \n%v\n", resp) + // modify newUser's own name - modRequest := UserRequest{Username: "myNewName"} + modRequest := UserRequest{Username: "myNewName", Active: true} newUser.Username = modRequest.Username code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -400,7 +409,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.NoError(t, err) // modify Admin's name (ILLEGAL) - modRequest = UserRequest{Username: "myNewName"} + modRequest = UserRequest{Username: "myNewName", Active: true} newUser.Username = modRequest.Username code, resp, err = helper.TestEndpoint(router, token, "/api/users/1", "PUT", helper.KeyModels{"user": modRequest}) @@ -408,7 +417,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.Equalf(t, 403, code, "Response body: \n%v\n", resp) // modify newUser's own email - modRequest = UserRequest{Mail: "my@new.email"} + modRequest = UserRequest{Mail: "my@new.email", Active: true} newUser.Mail = modRequest.Mail code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -419,7 +428,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.NoError(t, err) // modify Admin's own email (ILLEGAL) - modRequest = UserRequest{Mail: "my@new.email"} + modRequest = UserRequest{Mail: "my@new.email", Active: true} newUser.Mail = modRequest.Mail code, resp, err = helper.TestEndpoint(router, token, "/api/users/1", "PUT", helper.KeyModels{"user": modRequest}) @@ -427,7 +436,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.Equalf(t, 403, code, "Response body: \n%v\n", resp) // modify newUser's role (ILLEGAL) - modRequest = UserRequest{Role: "Admin"} + modRequest = UserRequest{Role: "Admin", Active: true} newUser.Role = modRequest.Role code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -436,7 +445,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.Equalf(t, 403, code, "Response body: \n%v\n", resp) // modify newUser's password - modRequest = UserRequest{Password: "5tr0ng_pw!"} + modRequest = UserRequest{Password: "5tr0ng_pw!", Active: true} code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", helper.KeyModels{"user": modRequest}) @@ -452,7 +461,7 @@ func TestModifyAddedUserAsUser(t *testing.T) { assert.NoError(t, err) // modify Admin's password (ILLEGAL) - modRequest = UserRequest{Password: "4dm1ns_pw!"} + modRequest = UserRequest{Password: "4dm1ns_pw!", Active: true} code, resp, err = helper.TestEndpoint(router, token, "/api/users/1", "PUT", helper.KeyModels{"user": modRequest}) assert.NoError(t, err) @@ -487,7 +496,7 @@ func TestInvalidUserUpdate(t *testing.T) { // try PUT with userID that does not exist // should result in not found - modRequest := UserRequest{Password: "longenough"} + modRequest := UserRequest{Password: "longenough", Active: true} code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID+1), "PUT", helper.KeyModels{"user": modRequest}) @@ -513,7 +522,7 @@ func TestInvalidUserUpdate(t *testing.T) { assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) // modify newUser's email with INVALID email - modRequest = UserRequest{Mail: "notEmail"} + modRequest = UserRequest{Mail: "notEmail", Active: true} code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", helper.KeyModels{"user": modRequest}) @@ -521,7 +530,7 @@ func TestInvalidUserUpdate(t *testing.T) { assert.Equalf(t, 400, code, "Response body: \n%v\n", resp) // modify newUser's role with INVALID role - modRequest = UserRequest{Role: "noRole"} + modRequest = UserRequest{Role: "noRole", Active: true} code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", helper.KeyModels{"user": modRequest}) @@ -563,7 +572,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { newUser.Password = "" // modify newUser's name - modRequest := UserRequest{Username: "NewUsername"} + modRequest := UserRequest{Username: "NewUsername", Active: true} newUser.Username = modRequest.Username code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -574,7 +583,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { assert.NoError(t, err) // modify newUser's email - modRequest = UserRequest{Mail: "new@e.mail"} + modRequest = UserRequest{Mail: "new@e.mail", Active: true} newUser.Mail = modRequest.Mail code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -585,7 +594,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { assert.NoError(t, err) // modify newUser's role - modRequest = UserRequest{Role: "Admin"} + modRequest = UserRequest{Role: "Admin", Active: true} newUser.Role = modRequest.Role code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", @@ -596,7 +605,7 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { assert.NoError(t, err) // modify newUser's password - modRequest = UserRequest{Password: "4_g00d_pw!"} + modRequest = UserRequest{Password: "4_g00d_pw!", Active: true} code, resp, err = helper.TestEndpoint(router, token, fmt.Sprintf("/api/users/%v", newUserID), "PUT", helper.KeyModels{"user": modRequest}) @@ -610,6 +619,30 @@ func TestModifyAddedUserAsAdmin(t *testing.T) { Password: modRequest.Password, }) assert.NoError(t, err) + + // authenticate as admin + token, err = helper.AuthenticateForTest(router, + "/api/authenticate", "POST", helper.AdminCredentials) + assert.NoError(t, err) + + // modify newUser's Active status + modRequest = UserRequest{Active: false} + code, resp, err = helper.TestEndpoint(router, token, + fmt.Sprintf("/api/users/%v", newUserID), "PUT", + helper.KeyModels{"user": modRequest}) + assert.NoError(t, err) + assert.Equalf(t, 200, code, "Response body: \n%v\n", resp) + + // try to login as newUser with the modified active status + // should NOT work anymore! + code, resp, err = helper.TestEndpoint(router, token, + "/api/authenticate", "POST", + UserRequest{ + Username: newUser.Username, + Password: "4_g00d_pw!", + }) + assert.NoError(t, err) + assert.Equalf(t, 401, code, "Response body: \n%v\n", resp) } func TestDeleteUser(t *testing.T) { diff --git a/routes/user/user_validators.go b/routes/user/user_validators.go index f3e750f..517e1ca 100644 --- a/routes/user/user_validators.go +++ b/routes/user/user_validators.go @@ -18,6 +18,7 @@ type validUpdatedRequest struct { Password string `form:"Password" validate:"omitempty,min=6"` Role string `form:"Role" validate:"omitempty,oneof=Admin User Guest"` Mail string `form:"Mail" validate:"omitempty,email"` + Active bool `form:"Active" validate:"omitempty"` } type updateUserRequest struct { @@ -62,6 +63,15 @@ func (r *updateUserRequest) updatedUser(role interface{}, u.Role = r.Role } + // Only the Admin must be able to update users Active state + if r.Active != u.Active { + if role != "Admin" { + return u, fmt.Errorf("Only Admin can update user's Active state") + } else { + u.Active = r.Active + } + } + // Update the username making sure is NOT taken var testUser User if err := testUser.ByUsername(r.Username); err == nil { @@ -101,6 +111,7 @@ func (r *addUserRequest) createUser() User { u.Password = r.Password u.Mail = r.Mail u.Role = r.Role + u.Active = true return u }