diff --git a/__debug_bin b/__debug_bin deleted file mode 100755 index 9383cd2b59178ea8f95c1419aefe68f567ab55fc..0000000000000000000000000000000000000000 Binary files a/__debug_bin and /dev/null differ diff --git a/data/test.db b/data/test.db index 8616989263916b184bb39769ac9d9f20f3a3e14e..6632317d0cb45ca56b798a9830c7a18f68b98d9d 100644 Binary files a/data/test.db and b/data/test.db differ diff --git a/data/users.db b/data/users.db index ae68077b7f8523f5d7577885f3697c70c99ce8e9..aacb808a6df9d089bef233ea44695d3a7fc84678 100644 Binary files a/data/users.db and b/data/users.db differ diff --git a/go.mod b/go.mod index 5e2f5078e3d5ed48351c4ae2518b0f4753fec7e1..6ecac3ab834527f4e3bab3a9b21236911fd22e19 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module forge.grandlyon.com/apoyen/elections go 1.14 require ( - forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200504124323-b515b737f420 + forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200506130516-44169b4175cf github.com/jinzhu/gorm v1.9.12 golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index e6d2e9007e2ac22eaa075a0be7a3bca129e728ff..23c89f0b890bed63dfc48cd7d8467a6e1732ed6f 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200504124323-b515b737f420 h1:zMXCCzbXelZF53D4+YaHFwld3WYPlYaXaJdYwCWj3dg= forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200504124323-b515b737f420/go.mod h1:ajJR/1lQlFldcLXFE+PhHNEL/KhU0kW7bTeVUnaM574= +forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200506130516-44169b4175cf h1:qPCX0bepDzHy/JO1exHZY0i3M5+j0X86uY+11vevUSE= +forge.grandlyon.com/apoyen/sdk-go v0.0.0-20200506130516-44169b4175cf/go.mod h1:ajJR/1lQlFldcLXFE+PhHNEL/KhU0kW7bTeVUnaM574= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 5ae0952bcca906a21760a3e809e47297227100e8..ce8a4fe3e419e1971e6bbe19b02afbdcfa5133a9 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -27,11 +27,9 @@ type User struct { ID int `json:"id,omitempty"` IDOAuth string `json:"idOAuth,omitempry"` Login string `json:"login"` - DisplayName string `json:"displayName,omitempty"` Role string `json:"role"` IsAdmin bool `json:"isAdmin,omitempty"` Name string `json:"name,omitempty"` - Surname string `json:"surname,omitempty"` PasswordHash string `json:"-"` Password string `json:"password,omitempty"` } diff --git a/internal/auth/inmemory.go b/internal/auth/inmemory.go index 70aab983373267b572f4fb1c7aae5f8b2f2c4ad7..6cef4810e1478e0244b8b9dd53e65f952eae7c71 100644 --- a/internal/auth/inmemory.go +++ b/internal/auth/inmemory.go @@ -50,7 +50,7 @@ func (m Manager) HandleInMemoryLogin(w http.ResponseWriter, r *http.Request) { tokenData := TokenData{User: User{ID: user.ID, Login: user.Login, Role: user.Role}, XSRFToken: xsrfToken} tokens.Manager.StoreData(tokenData, m.Hostname, authTokenKey, 24*time.Hour, w) // Log the connexion - log.Logger.Printf("| %v (%v %v) | Login success | %v | %v", user.Login, user.Name, user.Surname, r.RemoteAddr, log.GetCityAndCountryFromRequest(r)) + log.Logger.Printf("| %v (%v) | Login success | %v | %v", user.Login, user.Name, r.RemoteAddr, log.GetCityAndCountryFromRequest(r)) } // ByID implements sort.Interface for []User based on the ID field @@ -150,10 +150,13 @@ func (d *DataHandler) UpdateUser(w http.ResponseWriter, req *http.Request) { } user.IDOAuth = newUser.IDOAuth user.Login = newUser.Login - user.DisplayName = newUser.DisplayName user.Name = newUser.Name - user.Surname = newUser.Surname user.Role = newUser.Role + if user.Role == "ADMIN" { + user.IsAdmin = true + } else { + user.IsAdmin = false + } if newUser.Password != "" { hash, err := bcrypt.GenerateFromPassword([]byte(newUser.Password), bcrypt.DefaultCost) if err != nil { diff --git a/internal/auth/oauth2.go b/internal/auth/oauth2.go index 854c7575234df45912c6a8800f8cb7f162d37a38..ca1dc276977b1bc395f87e0dfae355897818d5e6 100644 --- a/internal/auth/oauth2.go +++ b/internal/auth/oauth2.go @@ -140,7 +140,7 @@ func (m Manager) HandleOAuth2Callback() http.Handler { tokenData := TokenData{User: user, XSRFToken: xsrfToken} tokens.Manager.StoreData(tokenData, m.Hostname, authTokenKey, 24*time.Hour, w) // Log the connexion - log.Logger.Printf("| %v (%v %v) | Login success | %v | %v", user.Login, user.Name, user.Surname, req.RemoteAddr, log.GetCityAndCountryFromRequest(req)) + log.Logger.Printf("| %v (%v) | Login success | %v | %v", user.Login, user.Name, req.RemoteAddr, log.GetCityAndCountryFromRequest(req)) // Redirect http.Redirect(w, r, "/", http.StatusFound) } @@ -163,30 +163,21 @@ func (d *DataHandler) addUserInMemory(userOauth2 UserOAuth2) (User, error) { for _, userRole := range userOauth2.Groups { if userRole != "" && (userRole == os.Getenv("ADMIN_GROUP")) { user.Role = "ADMIN" + user.IsAdmin = true + break } else if userRole != "" && (userRole == os.Getenv("VISUALIZER_GROUP")) { user.Role = "VISUALIZER" + user.IsAdmin = false + break } else { + fmt.Println(os.Getenv("ADMIN_GROUP") + " " + userRole) return user, errors.New("user not in an app group") } } user.IDOAuth = userOauth2.ID user.Login = userOauth2.Login - user.DisplayName = userOauth2.DisplayName user.Name = userOauth2.Name - user.Surname = userOauth2.Surname - var users []User - err := common.Load(UsersFile, &users) - if err != nil { - return user, errors.New("Error on loading user") - } - // Select the new id for the user - user.ID = 1 - for _, val := range users { - if user.ID <= val.ID { - user.ID = val.ID + 1 - } - } // Sauvegarder l'utilisateur dans InMemory d.createUser(user) return user, nil diff --git a/internal/models/capturer.go b/internal/models/capturer.go new file mode 100644 index 0000000000000000000000000000000000000000..f048bcbbfafbe3b5c661608a50f5944d1eb20651 --- /dev/null +++ b/internal/models/capturer.go @@ -0,0 +1,143 @@ +package models + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + + "forge.grandlyon.com/apoyen/elections/internal/auth" +) + +// HandleCapturer handle API calls on Capturer +func (d *DataHandler) HandleCapturer(w http.ResponseWriter, r *http.Request) { + id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Capturer/")) + switch method := r.Method; method { + case "GET": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.getCapturerAdmin(w, r, id) + case "CAPTURER": + d.getCapturerCapturer(w, r, id) + case "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + case "POST": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.postCapturerAdmin(w, r) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + + case "PUT": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.putCapturerAdmin(w, r, id) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + case "DELETE": + switch auth.GetLoggedUserTechnical(w, r).Role { + case "ADMIN": + d.deleteCapturerAdmin(w, r, id) + case "CAPTURER", "VISUALIZER": + http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) + default: + http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) + } + default: + http.Error(w, "method not allowed", 400) + } +} + +func (d *DataHandler) getCapturerAdmin(w http.ResponseWriter, r *http.Request, id int) { + if id != 0 { + var o Capturer + if err := d.db.Preload("DeskRounds").First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + json.NewEncoder(w).Encode(o) + } else { + var o []Capturer + d.db.Preload("DeskRounds").Find(&o) + json.NewEncoder(w).Encode(o) + } +} + +func (d *DataHandler) getCapturerCapturer(w http.ResponseWriter, r *http.Request, id int) { + user := d.getLoggedUser(w, r).(Capturer) + fmt.Println(user) + if id != 0 { + var o Capturer + if err := d.db.Preload("DeskRounds").First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + // fmt.Println(o) + if o.UserID != user.UserID { + http.Error(w, ErrorCannotAccessRessource, http.StatusForbidden) + return + } + json.NewEncoder(w).Encode(o) + } else { + var o []Capturer + d.db.Preload("DeskRounds").Where("id = ?", user.ID).Find(&o) + json.NewEncoder(w).Encode(o) + } +} + +func (d *DataHandler) postCapturerAdmin(w http.ResponseWriter, r *http.Request) { + var o Capturer + err := json.NewDecoder(r.Body).Decode(&o) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + var capturer Capturer + if err := d.db.Where("user_id = ?", o.UserID).First(&capturer).Error; err == nil { + http.Error(w, "UserID is already bind to a Capturer", http.StatusInternalServerError) + return + } + d.db.Create(&o) + d.db.Last(&o) + json.NewEncoder(w).Encode(o) + +} + +func (d *DataHandler) putCapturerAdmin(w http.ResponseWriter, r *http.Request, id int) { + var o Capturer + if err := d.db.Preload("DeskRounds").First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + var capturer Capturer + err := json.NewDecoder(r.Body).Decode(&capturer) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + o.Name = capturer.Name + d.db.Save(&o) + json.NewEncoder(w).Encode(o) + +} + +func (d *DataHandler) deleteCapturerAdmin(w http.ResponseWriter, r *http.Request, id int) { + if id != 0 { + var o Capturer + if err := d.db.First(&o, id).Error; err != nil { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + return + } + d.db.Delete(&o) + } else { + http.Error(w, ErrorIDIsMissing, http.StatusNotFound) + } +} diff --git a/internal/models/models.go b/internal/models/models.go index 24bcd4fc1086862358bacab665703f928c9e4e23..858791b68c303133d158354ab7e38f6a1ab9af38 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -5,6 +5,7 @@ import ( "strings" "time" + "forge.grandlyon.com/apoyen/elections/internal/auth" "github.com/jinzhu/gorm" // Needed for sqlite @@ -16,159 +17,173 @@ type DataHandler struct { db *gorm.DB } -// ErrorIDDoesNotExist = "id does not exist" +// ErrorIDDoesNotExist = "id does not exist" with 404 http.StatusNotFound const ErrorIDDoesNotExist = "id does not exist" -// ErrorIDIsMissing = "id is missing" +// ErrorIDIsMissing = "id is missing" with 404 http.StatusNotFound const ErrorIDIsMissing = "id is missing" -// ErrorCannotAccessRessource = "You can not access this ressource" +// ErrorCannotAccessRessource = "You can not access this ressource" with 403 http.StatusForbidden const ErrorCannotAccessRessource = "You can not access this ressource" -// ErrorRoleOfLoggedUser = "Could not get role of logged user" +// ErrorRoleOfLoggedUser = "Could not get role of logged user" with 500 http.StatusInternalServerError const ErrorRoleOfLoggedUser = "Could not get role of logged user" -// ErrorNotAuthorizeMethodOnRessource = "You're not authorize to execute this method on this ressource." +// ErrorNotAuthorizeMethodOnRessource = "You're not authorize to execute this method on this ressource." with 405 http.StatusMethodNotAllowed const ErrorNotAuthorizeMethodOnRessource = "You're not authorize to execute this method on this ressource." -type election struct { +// Election +type Election struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - name string - ballotType string - areas []area - rounds []round + Name string + BallotType string + Areas []Area + Rounds []Round } -type area struct { +// Area +type Area struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - electionID uint - name string - seatNumber uint - mapID string - sections []section + ElectionID uint + Name string + SeatNumber uint + MapID string + Sections []Section } -type section struct { +// Section +type Section struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - areaID uint - name string - seatNumber uint - mapID string - desks []desk + AreaID uint + Name string + SeatNumber uint + MapID string + Desks []Desk } -type desk struct { +// Desk +type Desk struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - sectionID uint - name string - subscribed uint - witnessDesk bool + SectionID uint + Name string + Subscribed uint + WitnessDesk bool } -type party struct { +// Party +type Party struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - name string - color string - candidateList []candidateList + Name string + Color string + CandidateList []CandidateList } -type capturer struct { +// Capturer +type Capturer struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - userID int `gorm:"not null;unique"` - name string - deskRounds []deskRound + UserID int `gorm:"not null;unique"` + Name string + DeskRounds []DeskRound `gorm:"many2many:capturer_deskrounds;"` } -type parameter struct { +// Parameter +type Parameter struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - countBalnkAndNull bool - showOnlyCompleted bool - showMap bool + CountBalnkAndNull bool + ShowOnlyCompleted bool + ShowMap bool } -type round struct { +// Round +type Round struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - electionID uint - parameter parameter - name string - date time.Time - tour uint - deskRounds []deskRound - candidateLists []candidateList + ElectionID uint + Parameter Parameter + Name string + Date time.Time + Tour uint + DeskRounds []DeskRound + CandidateLists []CandidateList } -type deskRound struct { +// DeskRound +type DeskRound struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - roundID uint - completed bool - dateCompletion time.Time - validated bool - votes []vote + RoundID uint + Capturers []Capturer `gorm:"many2many:capturer_deskrounds;"` + Completed bool + DateCompletion time.Time + Validated bool + Votes []Vote } -type candidateList struct { + +// CandidateList +type CandidateList struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - partyID uint - roundID uint - area area `gorm:"foreignkey:AreaRefer"` - name string - candidates []candidate - votes []vote + PartyID uint + RoundID uint + Area Area `gorm:"foreignkey:AreaRefer"` + Name string + Candidates []Candidate + Votes []Vote } -type candidate struct { +// Candidate +type Candidate struct { ID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - candidateListID uint - fullName string - rank uint - communityCounseller bool - birthdate time.Time - potentialIncompatibility bool - refused bool - removed bool -} - -type vote struct { - deskRoundID uint `gorm:"primary_key"` - candidateListID uint `gorm:"primary_key"` + CandidateListID uint + FullName string + Rank uint + CommunityCounseller bool + Birthdate time.Time + PotentialIncompatibility bool + Refused bool + Removed bool +} + +// Vote +type Vote struct { + DeskRoundID uint `gorm:"primary_key"` + CandidateListID uint `gorm:"primary_key"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt *time.Time `json:"-"` - voiceNumber uint - blank bool - null bool + VoiceNumber uint + Blank bool + Null bool } // NewDataHandler init a DataHandler and returns a pointer to it @@ -180,18 +195,18 @@ func NewDataHandler() *DataHandler { db.LogMode(true) // Migrate the schema - db.AutoMigrate(&capturer{}) - db.AutoMigrate(&election{}) - db.AutoMigrate(&area{}) - db.AutoMigrate(§ion{}) - db.AutoMigrate(&desk{}) - db.AutoMigrate(&round{}) - db.AutoMigrate(&deskRound{}) - db.AutoMigrate(&party{}) - db.AutoMigrate(&candidateList{}) - db.AutoMigrate(&candidate{}) - db.AutoMigrate(&vote{}) - db.AutoMigrate(¶meter{}) + db.AutoMigrate(&Capturer{}) + db.AutoMigrate(&Election{}) + db.AutoMigrate(&Area{}) + db.AutoMigrate(&Section{}) + db.AutoMigrate(&Desk{}) + db.AutoMigrate(&Round{}) + db.AutoMigrate(&DeskRound{}) + db.AutoMigrate(&Party{}) + db.AutoMigrate(&CandidateList{}) + db.AutoMigrate(&Candidate{}) + db.AutoMigrate(&Vote{}) + db.AutoMigrate(&Parameter{}) return &DataHandler{db: db} } @@ -199,32 +214,24 @@ func NewDataHandler() *DataHandler { func (d *DataHandler) ProcessAPI(w http.ResponseWriter, r *http.Request) { api := strings.Split(strings.TrimPrefix(r.URL.Path, "/api/"), "/")[0] switch api { + case "Capturer": + d.HandleCapturer(w, r) } } func (d *DataHandler) getLoggedUser(w http.ResponseWriter, r *http.Request) interface{} { - // user := auth.GetLoggedUserTechnical(w, r) - // if user.Role != "" && (user.Role == "BANKER") { - // var o UserBanker - // if err := d.db.Where(reqUserID, user.ID).First(&o).Error; err != nil { - // o := UserBanker{UserID: user.ID, Name: user.Login} - // d.db.Create(&o) - // d.db.Where(reqUserID, user.ID).First(&o) - // return o - // } - // return o - // } else if user.Role != "" && (user.Role == "CLIENT") { - // var o UserClient - // if err := d.db.Where(reqUserID, user.ID).First(&o).Error; err != nil { - // o := UserClient{UserID: user.ID, Name: user.Login} - // d.db.Create(&o) - // d.db.Where(reqUserID, user.ID).First(&o) - // return o - // } - - // return o - // } + user := auth.GetLoggedUserTechnical(w, r) + if user.Role != "" && (user.Role == "CAPTURER") { + var o Capturer + if err := d.db.Where("user_id = ?", user.ID).First(&o).Error; err != nil { + o := Capturer{UserID: user.ID, Name: user.Login} + d.db.Create(&o) + d.db.First(&o, user.ID) + return o + } + return o + } return nil } diff --git a/internal/rootmux/admin_test.go b/internal/rootmux/admin_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ba9dc3b2045ff080574b25098862fc99febdc263 --- /dev/null +++ b/internal/rootmux/admin_test.go @@ -0,0 +1,42 @@ +package rootmux + +import ( + "encoding/json" + "testing" + + "forge.grandlyon.com/apoyen/elections/internal/auth" + "forge.grandlyon.com/apoyen/sdk-go/pkg/tester" +) + +/** +Banker TESTS (those tests are to check the bankers rights) +**/ +func AdminTests(t *testing.T) { + // Create the tester + ts, do, _ := createTester(t) + defer ts.Close() // Close the tester + tests := func() { + // Get the XSRF Token + response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") + token := auth.TokenData{} + json.Unmarshal([]byte(response), &token) + xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + + // Create a capturer + do("POST", "/api/Capturer", xsrfHeader, `{"UserID":1,"Name":"Capturer"}`, 200, `{"ID":3,"UserID":1,"Name":"Capturer","DeskRounds":null}`) + // Get the capturer + do("GET", "/api/Capturer/1", xsrfHeader, ``, 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":[]}`) + // Get all the capturer + do("GET", "/api/Capturer/", xsrfHeader, ``, 200, `[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":[]},{"ID":2,"UserID":3,"Name":"Capturer","DeskRounds":[]},{"ID":3,"UserID":1,"Name":"Capturer","DeskRounds":[]}]`) + // Update a capturer + do("PUT", "/api/Capturer/1", xsrfHeader, `{"ID":1,"UserID":2,"Name":"capturer"}`, 200, `{"ID":1,"UserID":2,"Name":"capturer","DeskRounds":[]}`) + // Delete a capturer + do("DELETE", "/api/Capturer/3", xsrfHeader, ``, 200, ``) + + } + // Do a in memory login with an known admin + do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "") + tests() + // Try to logout (must pass) + do("GET", "/Logout", noH, "", 200, "Logout OK") +} diff --git a/internal/rootmux/capturer_test.go b/internal/rootmux/capturer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..741c7a8a269c7540b783024d381255a7d4d29b4a --- /dev/null +++ b/internal/rootmux/capturer_test.go @@ -0,0 +1,44 @@ +package rootmux + +import ( + "encoding/json" + "testing" + + "forge.grandlyon.com/apoyen/elections/internal/auth" + "forge.grandlyon.com/apoyen/sdk-go/pkg/tester" +) + +/** +Banker TESTS (those tests are to check the bankers rights) +**/ +func CapturerTests(t *testing.T) { + // Create the tester + ts, do, _ := createTester(t) + defer ts.Close() // Close the tester + tests := func() { + // Get the XSRF Token + response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") + token := auth.TokenData{} + json.Unmarshal([]byte(response), &token) + xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + + // Create a capturer should fail with 405 + do("POST", "/api/Capturer", xsrfHeader, `{"userID":2,"name":"Capturer"}`, 405, `You're not authorize to execute this method on this ressource.`) + // Get the capturer connected + do("GET", "/api/Capturer/1", xsrfHeader, "", 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":[]}`) + // Get another capturer should fail with 405 + do("GET", "/api/Capturer/2", xsrfHeader, "", 403, `You can not access this ressource`) + // Get all the capturer return only the capturer connected + do("GET", "/api/Capturer/", xsrfHeader, "", 200, `[{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":[]}]`) + // Update a capturer should fail with 405 + do("PUT", "/api/Capturer/1", xsrfHeader, `{"ID":1,"UserID":2,"Name":"capturer"}`, 405, `You're not authorize to execute this method on this ressource.`) + // Delete a capturer should fail with 405 + do("DELETE", "/api/Capturer/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`) + + } + // Do a in memory login with an known admin + do("POST", "/Login", noH, `{"login": "capturer","password": "password"}`, 200, "") + tests() + // Try to logout (must pass) + do("GET", "/Logout", noH, "", 200, "Logout OK") +} diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go index 396912e5d990dfba9e7dd73bcd16fcaa232c1e92..62facc32e65584f1cbab90017866450e88ff90a4 100644 --- a/internal/rootmux/rootmux_test.go +++ b/internal/rootmux/rootmux_test.go @@ -55,6 +55,12 @@ func TestAll(t *testing.T) { resetData(t) appTests(t) + resetData(t) + AdminTests(t) + resetData(t) + CapturerTests(t) + resetData(t) + VisualizerTests(t) os.RemoveAll("./data") } @@ -79,8 +85,9 @@ func appTests(t *testing.T) { response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") token := auth.TokenData{} json.Unmarshal([]byte(response), &token) - // xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 500, `UserID is already bind to a Capturer`) } // Do an OAuth2 login with an known admin do("GET", "/OAuth2Login", noH, "", 200, "<!DOCTYPE html>") @@ -104,8 +111,11 @@ func resetData(t *testing.T) { response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") token := auth.TokenData{} json.Unmarshal([]byte(response), &token) - // xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + // Create a capturer + do("POST", "/api/Capturer", xsrfHeader, `{"UserID":2,"Name":"Capturer"}`, 200, `{"ID":1,"UserID":2,"Name":"Capturer","DeskRounds":null}`) + do("POST", "/api/Capturer", xsrfHeader, `{"UserID":3,"Name":"Capturer"}`, 200, `{"ID":2,"UserID":3,"Name":"Capturer","DeskRounds":null}`) } do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "") init() diff --git a/internal/rootmux/visualizer_test.go b/internal/rootmux/visualizer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8a8b94909a0f9481bcc048f041e7ab12787cb46f --- /dev/null +++ b/internal/rootmux/visualizer_test.go @@ -0,0 +1,42 @@ +package rootmux + +import ( + "encoding/json" + "testing" + + "forge.grandlyon.com/apoyen/elections/internal/auth" + "forge.grandlyon.com/apoyen/sdk-go/pkg/tester" +) + +/** +Banker TESTS (those tests are to check the bankers rights) +**/ +func VisualizerTests(t *testing.T) { + // Create the tester + ts, do, _ := createTester(t) + defer ts.Close() // Close the tester + tests := func() { + // Get the XSRF Token + response := do("GET", "/api/common/WhoAmI", noH, "", 200, "") + token := auth.TokenData{} + json.Unmarshal([]byte(response), &token) + xsrfHeader := tester.Header{Key: "XSRF-TOKEN", Value: token.XSRFToken} + + // Create a capturer should fail with 405 + do("POST", "/api/Capturer", xsrfHeader, `{"userID":2,"name":"Capturer"}`, 405, `You're not authorize to execute this method on this ressource.`) + // Get a capturer should fail with 405 + do("GET", "/api/Capturer/1", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`) + // Get all the capturer should fail with 405 + do("GET", "/api/Capturer/", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`) + // Update a capturer should fail with 405 + do("PUT", "/api/Capturer/1", xsrfHeader, `{"ID":1,"UserID":2,"Name":"capturer"}`, 405, `You're not authorize to execute this method on this ressource.`) + // Delete a capturer should fail with 405 + do("DELETE", "/api/Capturer/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`) + + } + // Do a in memory login with an known admin + do("POST", "/Login", noH, `{"login": "visualizer","password": "password"}`, 200, "") + tests() + // Try to logout (must pass) + do("GET", "/Logout", noH, "", 200, "Logout OK") +}