Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ You'll need to set up these values in your environment. Ask an RTP for OIDC cred
```
VOTE_HOST=http://localhost:8080
VOTE_JWT_SECRET=
VOTE_MONGO_DB=
VOTE_MONGODB_URI=
VOTE_OIDC_ID=vote
VOTE_OIDC_SECRET=
Expand Down
1 change: 0 additions & 1 deletion database/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ func (poll *Poll) GetResult(ctx context.Context) ([]map[string]int, error) {
case POLL_TYPE_RANKED:
// We want to store those that were eliminated
eliminated := make([]string, 0)
eliminated = append(eliminated, "Isaac Ingram", "Charlotte George")

// Get all votes
cursor, err := Client.Database(db).Collection("votes").Aggregate(ctx, mongo.Pipeline{
Expand Down
92 changes: 74 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ package main
import (
"encoding/json"
"fmt"
cshAuth "github.com/computersciencehouse/csh-auth"
"github.com/computersciencehouse/vote/database"
"github.com/computersciencehouse/vote/sse"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive"
"html/template"
"mvdan.cc/xurls/v2"
"log"
"net/http"
"os"
"sort"
"strconv"
"strings"
"time"

cshAuth "github.com/computersciencehouse/csh-auth"
"github.com/computersciencehouse/vote/database"
"github.com/computersciencehouse/vote/sse"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson/primitive"
"mvdan.cc/xurls/v2"
)

func inc(x int) string {
Expand Down Expand Up @@ -280,18 +282,41 @@ func main() {
PollId: pId,
UserId: claims.UserInfo.Username,
}

voted := make([]bool, len(poll.Options))
max_num := len(vote.Options)

for _, opt := range poll.Options {
if c.PostForm(opt) != "" {
rank, err := strconv.Atoi(c.PostForm(opt))
if err != nil {
c.JSON(500, gin.H{"error": "error parsing votes"})
}
if rank > 0 {
vote.Options[opt] = rank
}
if c.PostForm(opt) == "" {
c.JSON(400, gin.H{"error": "did not fill out all rankings"})
return
}
rank, err := strconv.Atoi(c.PostForm(opt))
if err != nil {
c.JSON(400, gin.H{"error": "non-number ranking"})
return
}
if rank > 0 && rank <= max_num {
vote.Options[opt] = rank
voted[rank-1] = true
} else {
c.JSON(400, gin.H{"error": fmt.Sprintf("votes must be from 1 - %d", max_num)})
return
}
}
for num, vote := range voted {
if !vote {
c.JSON(400, gin.H{"error": fmt.Sprintf("no candidate ranked at #%d", num+1)})
return
}
}
if c.PostForm("writeinOption") != "" && c.PostForm("writein") != "" {
for candidate := range vote.Options {
if strings.EqualFold(candidate, strings.TrimSpace(c.PostForm("writeinOption"))) {
c.JSON(500, gin.H{"error": "write-in is already an option"})
return
}
}
rank, err := strconv.Atoi(c.PostForm("writein"))
if err != nil {
c.JSON(500, gin.H{"error": "error parsing votes"})
Expand Down Expand Up @@ -334,7 +359,10 @@ func main() {
}

if poll.Hidden && poll.CreatedBy != claims.UserInfo.Username {
c.JSON(403, gin.H{"Success": "Result Hidden"})
c.HTML(403, "hidden.tmpl", gin.H{
"Username": claims.UserInfo.Username,
"FullName": claims.UserInfo.FullName,
})
return
}

Expand Down Expand Up @@ -486,7 +514,7 @@ func main() {
r.Run()
}

func canVote(groups []string) bool {
func canVote(groups []string, username string) bool {
var active, fallCoop, springCoop bool
for _, group := range groups {
if group == "active" {
Expand All @@ -503,10 +531,38 @@ func canVote(groups []string) bool {
}
}

type Result struct {
Result bool `json:"result"`
}

// gatekeep
gatekeepURL := "https://conditional.csh.rit.edu/gatekeep/" + username
voteToken := os.Getenv("VOTE_TOKEN")
req, err := http.NewRequest("GET", gatekeepURL, nil)
if err != nil {
log.Fatal(err)
return false
}
req.Header.Add("X-VOTE-TOKEN", voteToken)

resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
return false
}
defer resp.Body.Close()

var result Result
err = json.NewDecoder(resp.Body).Decode(&result)
if err != nil {
log.Fatal(err)
return false
}
gatekeep := result.Result
if time.Now().Month() > time.July {
return active && !fallCoop
return active && !fallCoop && gatekeep
} else {
return active && !springCoop
return active && !springCoop && gatekeep
}
}

Expand Down
50 changes: 50 additions & 0 deletions templates/hidden.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>CSH Vote</title>
<!-- <link rel="stylesheet" href="https://themeswitcher.csh.rit.edu/api/get" /> -->
<link
rel="stylesheet"
href="https://assets.csh.rit.edu/csh-material-bootstrap/4.3.1/dist/csh-material-bootstrap.min.css"
media="screen"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
#lockdown {
width: 20%;
height: auto;
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="/">Vote</a>
<div class="nav navbar-nav ml-auto">
<div class="navbar-user">
<img src="https://profiles.csh.rit.edu/image/{{ .Username }}" />
<span class="text-light">{{ .FullName }}</span>
<a href="/auth/logout" style="color: #c3c3c3"><i>(logout)</i></a>
</div>
</div>
</div>
</nav>

<div
style="text-align: center; font-size: 1.2rem"
class="main p-5 error-page align-center"
>
<img id="lockdown" src="/static/material_lock.svg" alt="Attention!" />
<br />
<h2>The results are hidden!</h2>
<p>Looks like you aren't allowed to see the results.</p>
<p>
Please contact the owner of this poll or a Root Type Person if you think
this is an error.
</p>
</div>
</body>
</html>