diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml new file mode 100644 index 0000000..78b4c46 --- /dev/null +++ b/.github/workflows/sonarqube.yml @@ -0,0 +1,21 @@ +name: SonarQube + +on: + push: + branches: + - dev + + +jobs: + build: + name: Build and analyze + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: SonarSource/sonarqube-scan-action@v6 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} \ No newline at end of file diff --git a/constitutional.go b/constitutional.go index 70ce6c2..d9c98f6 100644 --- a/constitutional.go +++ b/constitutional.go @@ -151,8 +151,14 @@ func EvaluatePolls() { logging.Logger.WithFields(logrus.Fields{"method": "EvaluatePolls close"}).Error(err) continue } + announceStr := "The vote \"" + poll.ShortDescription + "\" has closed." + if !poll.Hidden { + announceStr += " Check out the results at " + pollLink + } else { + announceStr += " Results will be posted shortly." + } _, _, _, err = slackData.Client.SendMessage(slackData.AnnouncementsChannel, - slack.MsgOptionText("The vote \""+poll.ShortDescription+"\" has closed. Check out the results at "+pollLink, false)) + slack.MsgOptionText(announceStr, false)) if err != nil { logging.Logger.WithFields(logrus.Fields{"method": "EvaluatePolls announce"}).Error(err) } diff --git a/database/poll.go b/database/poll.go index bc1ab84..01c2b7c 100644 --- a/database/poll.go +++ b/database/poll.go @@ -312,7 +312,6 @@ func (poll *Poll) GetResult(ctx context.Context) ([]map[string]int, error) { // In that case, it's a tie? if val != minVote { end = false - break } } if end { diff --git a/main.go b/main.go index 45c7596..0a95d6e 100644 --- a/main.go +++ b/main.go @@ -67,6 +67,7 @@ func main() { r.GET("/auth/callback", csh.AuthCallback) r.GET("/auth/logout", csh.AuthLogout) + // TODO: change ALL the response codes to use http.(actual description) r.GET("/", csh.AuthWrapper(func(c *gin.Context) { cl, _ := c.Get("cshauth") claims := cl.(cshAuth.CSHClaims) @@ -298,8 +299,23 @@ func main() { UserId: claims.UserInfo.Username, } - maxNum := len(poll.Options) - voted := make([]bool, maxNum) + fmt.Println(poll.Options) + + for _, option := range poll.Options { + optionRankStr := c.PostForm(option) + optionRank, err := strconv.Atoi(optionRankStr) + + if len(optionRankStr) < 1 { + continue + } + if err != nil { + c.JSON(400, gin.H{"error": "non-number ranking"}) + return + } + + vote.Options[option] = optionRank + } + // process write-in if c.PostForm("writeinOption") != "" && c.PostForm("writein") != "" { for candidate := range vote.Options { @@ -318,27 +334,24 @@ func main() { return } vote.Options[c.PostForm("writeinOption")] = rank - maxNum += 1 //you can rank all options in the poll PLUS one } - for _, opt := range poll.Options { - option := c.PostForm(opt) - rank, err := strconv.Atoi(option) - if len(option) < 1 { - continue - } - if err != nil { - c.JSON(400, gin.H{"error": "non-number ranking"}) - return - } + maxNum := len(vote.Options) + voted := make([]bool, maxNum) + + for _, rank := range vote.Options { if rank > 0 && rank <= maxNum { - vote.Options[opt] = rank + if voted[rank-1] { + c.JSON(400, gin.H{"error": "You ranked two or more candidates at the same level"}) + return + } voted[rank-1] = true } else { c.JSON(400, gin.H{"error": fmt.Sprintf("votes must be from 1 - %d", maxNum)}) return } } + rankedCandidates := len(vote.Options) for _, voteOpt := range vote.Options { if voteOpt > rankedCandidates { diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..24c2592 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1 @@ +sonar.projectKey=ComputerScienceHouse_vote_c5ba863d-30d7-4fa9-97dd-4f2c58f8f5fa \ No newline at end of file