package models import ( "encoding/json" "errors" "net/http" "strconv" "strings" "time" "forge.grandlyon.com/apoyen/elections/internal/auth" "github.com/jinzhu/gorm" ) func (d *DataHandler) handleVote(w http.ResponseWriter, r *http.Request) { id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Vote/")) switch method := r.Method; method { case "GET": switch auth.GetLoggedUserTechnical(w, r).Role { case "ADMIN", "CAPTURER", "VISUALIZER": d.getVote(w, r) default: http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) } case "POST": switch auth.GetLoggedUserTechnical(w, r).Role { case "ADMIN", "CAPTURER": d.postVote(w, r) case "VISUALIZER": http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) default: http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) } case "PUT": switch auth.GetLoggedUserTechnical(w, r).Role { case "ADMIN", "CAPTURER": d.putVote(w, r, id) case "VISUALIZER": http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed) default: http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError) } case "DELETE": switch auth.GetLoggedUserTechnical(w, r).Role { case "ADMIN", "CAPTURER": d.deleteVote(w, r, id) case "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) getVote(w http.ResponseWriter, r *http.Request) { var o []Vote d.db.Find(&o) json.NewEncoder(w).Encode(o) } func (d *DataHandler) postVote(w http.ResponseWriter, r *http.Request) { var o Vote err := json.NewDecoder(r.Body).Decode(&o) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } var voteFound Vote if o.Blank { d.db.First(&voteFound, "desk_round_id = ? AND blank = ?", o.DeskRoundID, o.Blank) if voteFound.ID != 0 { http.Error(w, ErrorVoteExist, http.StatusInternalServerError) return } } else if o.NullVote { d.db.First(&voteFound, "desk_round_id = ? AND null_vote = ?", o.DeskRoundID, o.NullVote) if voteFound.ID != 0 { http.Error(w, ErrorVoteExist, http.StatusInternalServerError) return } } else { d.db.First(&voteFound, "desk_round_id = ? AND candidate_list_id = ?", o.DeskRoundID, o.CandidateListID) if voteFound.ID != 0 { http.Error(w, ErrorVoteExist, http.StatusInternalServerError) return } } if !o.Blank && !o.NullVote { // Check that CandidateListID exist var candidateList CandidateList if err := d.db.First(&candidateList, o.CandidateListID).Error; err != nil { http.Error(w, ErrorParentNotFound, http.StatusInternalServerError) return } } // Check that deskRound exist var deskRound DeskRound if err := d.db.Preload("Votes").First(&deskRound, o.DeskRoundID).Error; err != nil { http.Error(w, ErrorParentNotFound, http.StatusInternalServerError) return } d.db.Create(&o) d.db.Last(&o) json.NewEncoder(w).Encode(o) } func (d *DataHandler) putVote(w http.ResponseWriter, r *http.Request, id int) { var o Vote if err := d.db.First(&o, id).Error; err != nil { http.Error(w, ErrorIDIsMissing, http.StatusNotFound) return } var vote Vote err := json.NewDecoder(r.Body).Decode(&vote) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // check that objects are the same if o.CandidateListID != vote.CandidateListID || o.DeskRoundID != vote.DeskRoundID { http.Error(w, "Les objets ne correspondent pas", http.StatusInternalServerError) return } o.VoiceNumber = vote.VoiceNumber d.db.Save(&o) json.NewEncoder(w).Encode(o) } func (d *DataHandler) deleteVote(w http.ResponseWriter, r *http.Request, id int) { if id != 0 { var o Vote 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) } } func (vote *Vote) AfterSave(scope *gorm.Scope) error { var deskRound DeskRound if err := scope.DB().First(&deskRound, vote.DeskRoundID).Error; err != nil { return errors.New(ErrorValidateVote) } // Check deskCompletion var desk Desk if err := scope.DB().First(&desk, deskRound.DeskID).Error; err != nil { return errors.New(ErrorValidateVote) } var section Section if err := scope.DB().First(§ion, desk.SectionID).Error; err != nil { return errors.New(ErrorValidateVote) } var area Area if err := scope.DB().First(&area, section.AreaID).Error; err != nil { return errors.New(ErrorValidateVote) } var round Round if err := scope.DB().First(&round, deskRound.RoundID).Error; err != nil { return errors.New(ErrorValidateVote) } var candidateLists []CandidateList if err := scope.DB().Where("area_id = ? and round_id = ?", area.ID, round.ID).Find(&candidateLists).Error; err != nil { return errors.New(ErrorValidateVote) } var listNumberPerArea = len(candidateLists) var votes []Vote if err := scope.DB().Where("desk_round_id = ?", deskRound.ID).Find(&votes).Error; err != nil { return errors.New(ErrorValidateVote) } var votesNumberPerDesk = len(votes) if votesNumberPerDesk == (listNumberPerArea + 2) { deskRound.Completed = true deskRound.DateCompletion = time.Now() scope.DB().Save(&deskRound) } return nil }