Skip to content
Merged

Dev #122

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
13 changes: 13 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
VOTE_HOST=http://localhost:8080
VOTE_STATE=1000000
VOTE_OIDC_ID=develop
VOTE_JWT_SECRET=ahahaisdfjioThisShouldBeRandom
VOTE_OIDC_SECRET=no peeking (on wiki)
DEV_DISABLE_ACTIVE_FILTERS=true
DEV_FORCE_IS_EVALS=true
VOTE_CONDITIONAL_URL=https://conditional.csh.rit.edu/gatekeep
VOTE_TOKEN=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
VOTE_MONGODB_URI=mongodb://vote:c1f66aac6b4fafbef3c659371b8a50ed@mongodb/vote?authSource=admin
VOTE_ANNOUNCEMENTS_CHANNEL_ID=
VOTE_SLACK_APP_TOKEN=
VOTE_SLACK_BOT_TOKEN=
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.env*
.env
vote
.idea/
.vscode/
.vscode/

18 changes: 1 addition & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,7 @@ Implementation

## Configuration

If you're using the compose file, you'll need to ask an RTP for the vote-dev OIDC secret, and set it as `VOTE_OIDC_SECRET` in your environment

If you're not using the compose file, you'll need more of these

```
VOTE_HOST=http://localhost:8080
VOTE_JWT_SECRET=
VOTE_MONGODB_URI=
VOTE_OIDC_ID=
VOTE_OIDC_SECRET=
VOTE_STATE=
VOTE_TOKEN=
VOTE_CONDITIONAL_URL=https://conditional.csh.rit.edu/gatekeep/
VOTE_ANNOUNCEMENTS_CHANNEL_ID=
VOTE_SLACK_APP_TOKEN=
VOTE_SLACK_BOT_TOKEN=
```
Copy `.env.example` to `.env` and fill out the info

### Dev Overrides
`DEV_DISABLE_ACTIVE_FILTERS="true"` will disable the requirements that you be active to vote
Expand Down
72 changes: 54 additions & 18 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,29 @@ func GetHomepage(c *gin.Context) {
// A user may be unable to vote but should still be able to see a list of polls
user := GetUserData(c)

polls, err := database.GetOpenPolls(c)
pollResults, err := database.GetOpenPolls(c)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
sort.Slice(polls, func(i, j int) bool {
return polls[i].Id > polls[j].Id
sort.Slice(pollResults, func(i, j int) bool {
return pollResults[i].Id > pollResults[j].Id
})

polls := []*database.Poll{}

for _, poll := range pollResults {
if poll.HideForIneligible {
canVoteResult := canVote(user, *poll, poll.AllowedUsers)

if canVoteResult != 0 && canVoteResult != 9 {
continue
}
}

polls = append(polls, poll)
}

c.HTML(http.StatusOK, "index.tmpl", gin.H{
"Polls": polls,
"Username": user.Username,
Expand Down Expand Up @@ -139,23 +153,30 @@ func CreatePoll(c *gin.Context) {
return
}

// If title length exceeds 250 characters, return a bad request

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this error is impossible because of the max length placeholder, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could make an API request to do it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmmm you're so w comms

if len(c.PostForm("title")) > 250 {
c.JSON(http.StatusBadRequest, gin.H{"error": "title length exceeds limit of 250 characters"})
return
}

quorumType := c.PostForm("quorumType")

quorum, err := strconv.ParseFloat(quorumType, 64)
quorum = quorum / 100

poll := &database.Poll{
Id: "",
CreatedBy: user.Username,
Title: c.PostForm("title"),
Description: c.PostForm("description"),
VoteType: database.POLL_TYPE_SIMPLE,
OpenedTime: time.Now(),
Open: true,
QuorumType: quorum,
Gatekeep: c.PostForm("gatekeep") == "true",
AllowWriteIns: c.PostForm("allowWriteIn") == "true",
Hidden: c.PostForm("hidden") == "true",
Id: "",
CreatedBy: user.Username,
Title: c.PostForm("title"),
Description: c.PostForm("description"),
VoteType: database.POLL_TYPE_SIMPLE,
OpenedTime: time.Now(),
Open: true,
QuorumType: quorum,
Gatekeep: c.PostForm("gatekeep") == "true",
AllowWriteIns: c.PostForm("allowWriteIn") == "true",
Hidden: c.PostForm("hidden") == "true",
HideForIneligible: c.PostForm("hideIneligible") == "true",
}
if c.PostForm("rankedChoice") == "true" {
poll.VoteType = database.POLL_TYPE_RANKED
Expand Down Expand Up @@ -189,6 +210,10 @@ func CreatePoll(c *gin.Context) {
}
poll.AllowedUsers = GetEligibleVoters()
for user := range strings.SplitSeq(c.PostForm("waivedUsers"), ",") {
if len(user) == 0 { // When it's empty (and probably in other cases) the split can return an empty string, which changes the total
continue
}

poll.AllowedUsers = append(poll.AllowedUsers, strings.TrimSpace(user))
}
}
Expand Down Expand Up @@ -243,6 +268,19 @@ func GetPollResults(c *gin.Context) {

canModify := IsActiveRTP(user) || IsEboard(user) || ownsPoll(poll, user)

if poll.HideForIneligible {
canVoteResult := canVote(user, *poll, poll.AllowedUsers)

if canVoteResult != 0 && canVoteResult != 9 {
c.HTML(http.StatusForbidden, "unauthorized.tmpl", gin.H{
"Username": user.Username,
"FullName": user.FullName,
"EBoard": IsEboard(user),
})
return
}
}

if poll.Hidden && poll.Open {
c.HTML(http.StatusUnauthorized, "hidden.tmpl", gin.H{
"Id": poll.Id,
Expand All @@ -256,10 +294,8 @@ func GetPollResults(c *gin.Context) {

numVotes := 0

for _, v := range results {
for key := range v {
numVotes += v[key]
}
for key := range results[0] {
numVotes += results[0][key]
}

c.HTML(http.StatusOK, "result.tmpl", gin.H{
Expand Down
25 changes: 13 additions & 12 deletions database/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ import (
)

type Poll struct {
Id string `bson:"_id,omitempty"`
CreatedBy string `bson:"createdBy"`
Title string `bson:"title"`
Description string `bson:"description"`
VoteType string `bson:"voteType"`
Options []string `bson:"options"`
OpenedTime time.Time `bson:"openedTime"`
Open bool `bson:"open"`
Gatekeep bool `bson:"gatekeep"`
QuorumType float64 `bson:"quorumType"`
AllowedUsers []string `bson:"allowedUsers"`
AllowWriteIns bool `bson:"writeins"`
Id string `bson:"_id,omitempty"`
CreatedBy string `bson:"createdBy"`
Title string `bson:"title"`
Description string `bson:"description"`
VoteType string `bson:"voteType"`
Options []string `bson:"options"`
OpenedTime time.Time `bson:"openedTime"`
Open bool `bson:"open"`
Gatekeep bool `bson:"gatekeep"`
HideForIneligible bool `bson:"hideIneligible"`
QuorumType float64 `bson:"quorumType"`
AllowedUsers []string `bson:"allowedUsers"`
AllowWriteIns bool `bson:"writeins"`

// Prevent this poll from having progress displayed
// This is important for events like elections where the results shouldn't be visible mid vote
Expand Down
12 changes: 3 additions & 9 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,9 @@ services:
container_name: vote
depends_on:
- mongodb
environment:
VOTE_HOST: 'http://localhost:8080'
VOTE_JWT_SECRET: 4874c601dda90a01c7543c571be08680
VOTE_MONGODB_URI: "mongodb://vote:c1f66aac6b4fafbef3c659371b8a50ed@mongodb/vote?authSource=admin"
VOTE_OIDC_ID: vote-dev
VOTE_OIDC_SECRET: "${VOTE_OIDC_SECRET}"
VOTE_STATE: 27a28540e47ec786b7bdad03f83171b3
DEV_DISABLE_ACTIVE_FILTERS: "${DEV_DISABLE_ACTIVE_FILTERS}"
DEV_FORCE_IS_EVALS: "${DEV_FORCE_IS_EVALS}"
env_file:
- path: .env
required: false
ports:
- "127.0.0.1:8080:8080"

Expand Down
14 changes: 12 additions & 2 deletions templates/create.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
type="text"
class="form-control"
name="title"
placeholder="My Poll"
placeholder="My Poll (max 250 characters)"
maxlength="250"
required
>
</div>
Expand Down Expand Up @@ -100,7 +101,7 @@
value="50"
>
</div>
<div id="waivedUsers" class="input-group d-none">
<div id="waivedUsers" class="input-group d-none my-3">
<label for="waivedUsers" class="input-group-text">Waived Users</label>
<input
type="text"
Expand All @@ -109,6 +110,15 @@
placeholder="Comma separated list of usernames"
>
</div>
<div class="form-check form-switch fs-5 my-2">
<input
class="form-check-input"
type="checkbox"
name="hideIneligible"
value="true"
>
<label for="hidden" class="form-check-label">Hide Results for Members Who Cannot Vote</label>
</div>
</div>
{{ end }}

Expand Down
2 changes: 1 addition & 1 deletion templates/poll.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<h4>{{ .Description | MakeLinks }}</h4>
{{ end }}
{{ if eq .PollType "ranked" }}
<p>This is a Ranked Choice vote. Rank the candidates in order of your preference. 1 is most preferred, and {{ .RankedMax }} is least perferred. You may leave an option blank
<p>This is a Ranked Choice vote. Rank the candidates in order of your preference. 1 is most preferred, and {{ .RankedMax }} is least preferred. You may leave an option blank
if you do not prefer it at all.</p>
{{ end }}

Expand Down
2 changes: 1 addition & 1 deletion templates/unauthorized.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<div class="main p-5 error-page text-center">
<img id="lockdown" src="/static/material_lock.svg" alt="Attention!" width="256"/>
<h1 class="my-4">You're not authorized to vote!</h1>
<h1 class="my-4">You're not authorized to vote or view this poll!</h1>
<p class="fs-4 my-3">
It looks like you're either not marked as active, or you're on co-op
right now
Expand Down
Loading