Skip to content

Commit 62d186d

Browse files
Bootstrap 5 upgrade (#106)
* Changed all status codes to the http.StatusCode equivalent. Also changed some 500s to 400s where appropriate to indicate user error (#85) * Started working on navbar * More progress * working theme selector * Eboard vote link appears on all pages * Started working on navbar * More progress * working theme selector * Rebase with dev * Finished rebasing with dev * Added favicon import * Misc other stuff, navbar is responsive now * larger nav title * Quorum text input, create page basically done * Finished poll creation page * Ranked choice poll page is done * Actually use the hidden template * changed icon * Fixed vote count on eboard votes * Added display of total votes submitted to results * small fixes * fixed spacing between buttons for eboard vote on mobile * poll title wrapping in a different place * Changed underline to bold * Capitalize description placeholder text --------- Co-authored-by: Noah Hanford <bigspaceships56@gmail.com>
1 parent 8fd13c5 commit 62d186d

File tree

12 files changed

+402
-445
lines changed

12 files changed

+402
-445
lines changed

api.go

Lines changed: 71 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,14 @@ func GetHomepage(c *gin.Context) {
5757

5858
// GetClosedPolls Displays a page containing a list of all closed polls that the user created or voted in
5959
func GetClosedPolls(c *gin.Context) {
60-
cl, _ := c.Get("cshauth")
61-
claims := cl.(cshAuth.CSHClaims)
60+
user := GetUserData(c)
6261

63-
closedPolls, err := database.GetClosedVotedPolls(c, claims.UserInfo.Username)
62+
closedPolls, err := database.GetClosedVotedPolls(c, user.Username)
6463
if err != nil {
6564
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
6665
return
6766
}
68-
ownedPolls, err := database.GetClosedOwnedPolls(c, claims.UserInfo.Username)
67+
ownedPolls, err := database.GetClosedOwnedPolls(c, user.Username)
6968
if err != nil {
7069
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
7170
return
@@ -79,17 +78,17 @@ func GetClosedPolls(c *gin.Context) {
7978

8079
c.HTML(http.StatusOK, "closed.tmpl", gin.H{
8180
"ClosedPolls": closedPolls,
82-
"Username": claims.UserInfo.Username,
83-
"FullName": claims.UserInfo.FullName,
81+
"Username": user.Username,
82+
"FullName": user.FullName,
83+
"EBoard": IsEboard(user),
8484
})
8585
}
8686

8787
// GetPollById Retreives the information about a specific poll and displays it on the page, allowing the user to cast a ballot
8888
//
8989
// If the user is not eligible to vote in a particular poll, they are automatically redirected to the results page for that poll
9090
func GetPollById(c *gin.Context) {
91-
cl, _ := c.Get("cshauth")
92-
claims := cl.(cshAuth.CSHClaims)
91+
user := GetUserData(c)
9392
// This is intentionally left unprotected
9493
// We will check if a user can vote and redirect them to results if not later
9594

@@ -100,17 +99,16 @@ func GetPollById(c *gin.Context) {
10099
}
101100

102101
// If the user can't vote, just show them results
103-
if canVote(claims.UserInfo, *poll, poll.AllowedUsers) > 0 || !poll.Open {
102+
if canVote(user, *poll, poll.AllowedUsers) > 0 || !poll.Open {
104103
c.Redirect(http.StatusFound, "/results/"+poll.Id)
105104
return
106105
}
107-
108106
writeInAdj := 0
109107
if poll.AllowWriteIns {
110108
writeInAdj = 1
111109
}
112110

113-
canModify := IsActiveRTP(claims.UserInfo) || IsEboard(claims.UserInfo) || ownsPoll(poll, claims)
111+
canModify := IsActiveRTP(user) || IsEboard(user) || ownsPoll(poll, user)
114112

115113
c.HTML(200, "poll.tmpl", gin.H{
116114
"Id": poll.Id,
@@ -121,45 +119,40 @@ func GetPollById(c *gin.Context) {
121119
"RankedMax": fmt.Sprint(len(poll.Options) + writeInAdj),
122120
"AllowWriteIns": poll.AllowWriteIns,
123121
"CanModify": canModify,
124-
"Username": claims.UserInfo.Username,
125-
"FullName": claims.UserInfo.FullName,
122+
"Username": user.Username,
123+
"FullName": user.FullName,
124+
"EBoard": IsEboard(user),
126125
})
127126
}
128127

129128
// CreatePoll Submits the specific details of a new poll that a user wants to create to the database
130129
func CreatePoll(c *gin.Context) {
131-
cl, _ := c.Get("cshauth")
132-
claims := cl.(cshAuth.CSHClaims)
130+
user := GetUserData(c)
133131

134132
// If user is not active, display the unauthorized screen
135-
if !IsActive(claims.UserInfo) {
133+
if !IsActive(user) {
136134
c.HTML(http.StatusForbidden, "unauthorized.tmpl", gin.H{
137-
"Username": claims.UserInfo.Username,
138-
"FullName": claims.UserInfo.FullName,
135+
"Username": user.Username,
136+
"FullName": user.FullName,
137+
"EBoard": IsEboard(user),
139138
})
140139
return
141140
}
142141

143142
quorumType := c.PostForm("quorumType")
144-
var quorum float64
145-
switch quorumType {
146-
case "12":
147-
quorum = 1.0 / 2.0
148-
case "23":
149-
quorum = 2.0 / 3.0
150-
default:
151-
quorum = 1.0 / 2.0
152-
}
143+
144+
quorum, err := strconv.ParseFloat(quorumType, 64)
145+
quorum = quorum / 100
153146

154147
poll := &database.Poll{
155148
Id: "",
156-
CreatedBy: claims.UserInfo.Username,
149+
CreatedBy: user.Username,
157150
Title: c.PostForm("title"),
158151
Description: c.PostForm("description"),
159152
VoteType: database.POLL_TYPE_SIMPLE,
160153
OpenedTime: time.Now(),
161154
Open: true,
162-
QuorumType: float64(quorum),
155+
QuorumType: quorum,
163156
Gatekeep: c.PostForm("gatekeep") == "true",
164157
AllowWriteIns: c.PostForm("allowWriteIn") == "true",
165158
Hidden: c.PostForm("hidden") == "true",
@@ -186,10 +179,11 @@ func CreatePoll(c *gin.Context) {
186179
poll.Options = []string{"Pass", "Fail", "Abstain"}
187180
}
188181
if poll.Gatekeep {
189-
if !IsEboard(claims.UserInfo) {
182+
if !IsEboard(user) {
190183
c.HTML(http.StatusForbidden, "unauthorized.tmpl", gin.H{
191-
"Username": claims.UserInfo.Username,
192-
"FullName": claims.UserInfo.FullName,
184+
"Username": user.Username,
185+
"FullName": user.FullName,
186+
"EBoard": IsEboard(user),
193187
})
194188
return
195189
}
@@ -210,29 +204,28 @@ func CreatePoll(c *gin.Context) {
210204

211205
// GetCreatePage Displays the poll creation page to the user
212206
func GetCreatePage(c *gin.Context) {
213-
cl, _ := c.Get("cshauth")
214-
claims := cl.(cshAuth.CSHClaims)
207+
user := GetUserData(c)
215208

216209
// If the user is not active, display the unauthorized page
217-
if !IsActive(claims.UserInfo) {
210+
if !IsActive(user) {
218211
c.HTML(http.StatusForbidden, "unauthorized.tmpl", gin.H{
219-
"Username": claims.UserInfo.Username,
220-
"FullName": claims.UserInfo.FullName,
212+
"Username": user.Username,
213+
"FullName": user.FullName,
214+
"EBoard": IsEboard(user),
221215
})
222216
return
223217
}
224218

225219
c.HTML(http.StatusOK, "create.tmpl", gin.H{
226-
"Username": claims.UserInfo.Username,
227-
"FullName": claims.UserInfo.FullName,
228-
"IsEboard": IsEboard(claims.UserInfo),
220+
"Username": user.Username,
221+
"FullName": user.FullName,
222+
"EBoard": IsEboard(user),
229223
})
230224
}
231225

232226
// GetPollResults Displays the results page for a specific poll
233227
func GetPollResults(c *gin.Context) {
234-
cl, _ := c.Get("cshauth")
235-
claims := cl.(cshAuth.CSHClaims)
228+
user := GetUserData(c)
236229
// This is intentionally left unprotected
237230
// A user may be unable to vote but still interested in the results of a poll
238231

@@ -248,40 +241,52 @@ func GetPollResults(c *gin.Context) {
248241
return
249242
}
250243

251-
canModify := IsActiveRTP(claims.UserInfo) || IsEboard(claims.UserInfo) || ownsPoll(poll, claims)
244+
canModify := IsActiveRTP(user) || IsEboard(user) || ownsPoll(poll, user)
252245

253-
votesNeededForQuorum := int(poll.QuorumType * float64(len(poll.AllowedUsers)))
246+
if poll.Hidden && poll.Open {
247+
c.HTML(http.StatusUnauthorized, "hidden.tmpl", gin.H{
248+
"Id": poll.Id,
249+
"Title": poll.Title,
250+
"Description": poll.Description,
251+
"Username": user.Username,
252+
"FullName": user.FullName,
253+
})
254+
return
255+
}
256+
257+
fmt.Println(len(results))
254258
c.HTML(http.StatusOK, "result.tmpl", gin.H{
255259
"Id": poll.Id,
256260
"Title": poll.Title,
257261
"Description": poll.Description,
258262
"VoteType": poll.VoteType,
259263
"Results": results,
264+
"NumVotes": len(results),
260265
"IsOpen": poll.Open,
261266
"IsHidden": poll.Hidden,
262267
"CanModify": canModify,
263-
"CanVote": canVote(claims.UserInfo, *poll, poll.AllowedUsers),
264-
"Username": claims.UserInfo.Username,
265-
"FullName": claims.UserInfo.FullName,
268+
"CanVote": canVote(user, *poll, poll.AllowedUsers),
269+
"Username": user.Username,
270+
"FullName": user.FullName,
271+
"EBoard": IsEboard(user),
266272
"Gatekeep": poll.Gatekeep,
267273
"Quorum": strconv.FormatFloat(poll.QuorumType*100.0, 'f', 0, 64),
268274
"EligibleVoters": poll.AllowedUsers,
269-
"VotesNeededForQuorum": votesNeededForQuorum,
275+
"VotesNeededForQuorum": CalculateQuorum(*poll),
270276
})
271277
}
272278

273279
// VoteInPoll Submits a users' vote in a specific poll
274280
func VoteInPoll(c *gin.Context) {
275-
cl, _ := c.Get("cshauth")
276-
claims := cl.(cshAuth.CSHClaims)
281+
user := GetUserData(c)
277282

278283
poll, err := database.GetPoll(c, c.Param("id"))
279284
if err != nil {
280285
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
281286
return
282287
}
283288

284-
if canVote(claims.UserInfo, *poll, poll.AllowedUsers) > 0 || !poll.Open {
289+
if canVote(user, *poll, poll.AllowedUsers) > 0 || !poll.Open {
285290
c.Redirect(http.StatusFound, "/results/"+poll.Id)
286291
return
287292
}
@@ -293,9 +298,9 @@ func VoteInPoll(c *gin.Context) {
293298
}
294299

295300
if poll.VoteType == database.POLL_TYPE_SIMPLE {
296-
processSimpleVote(c, poll, pId, claims)
301+
processSimpleVote(c, poll, pId, user)
297302
} else if poll.VoteType == database.POLL_TYPE_RANKED {
298-
processRankedVote(c, poll, pId, claims)
303+
processRankedVote(c, poll, pId, user)
299304
} else {
300305
c.JSON(http.StatusInternalServerError, gin.H{"error": "Unknown Poll Type"})
301306
return
@@ -321,16 +326,15 @@ func VoteInPoll(c *gin.Context) {
321326
// If results are hidden, navigating to the results page of that poll will show
322327
// a page informing the user that the results are hidden, instead of the actual results
323328
func HidePollResults(c *gin.Context) {
324-
cl, _ := c.Get("cshauth")
325-
claims := cl.(cshAuth.CSHClaims)
329+
user := GetUserData(c)
326330

327331
poll, err := database.GetPoll(c, c.Param("id"))
328332
if err != nil {
329333
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
330334
return
331335
}
332336

333-
if !ownsPoll(poll, claims) {
337+
if !ownsPoll(poll, user) {
334338
c.JSON(http.StatusForbidden, gin.H{"error": "Only the creator can hide a poll result"})
335339
return
336340
}
@@ -345,7 +349,7 @@ func HidePollResults(c *gin.Context) {
345349
Id: "",
346350
PollId: pId,
347351
Date: primitive.NewDateTimeFromTime(time.Now()),
348-
User: claims.UserInfo.Username,
352+
User: user.Username,
349353
Action: "Hide Results",
350354
}
351355
err = database.WriteAction(c, &action)
@@ -359,8 +363,7 @@ func HidePollResults(c *gin.Context) {
359363

360364
// ClosePoll Sets a poll to no longer allow votes to be cast
361365
func ClosePoll(c *gin.Context) {
362-
cl, _ := c.Get("cshauth")
363-
claims := cl.(cshAuth.CSHClaims)
366+
user := GetUserData(c)
364367
// This is intentionally left unprotected
365368
// A user should be able to end their own polls, regardless of if they can vote
366369

@@ -375,8 +378,8 @@ func ClosePoll(c *gin.Context) {
375378
return
376379
}
377380

378-
if !ownsPoll(poll, claims) {
379-
if !IsActiveRTP(claims.UserInfo) && !IsEboard(claims.UserInfo) {
381+
if !ownsPoll(poll, user) {
382+
if !IsActiveRTP(user) && !IsEboard(user) {
380383
c.JSON(http.StatusForbidden, gin.H{"error": "You cannot end this poll."})
381384
return
382385
}
@@ -392,7 +395,7 @@ func ClosePoll(c *gin.Context) {
392395
Id: "",
393396
PollId: pId,
394397
Date: primitive.NewDateTimeFromTime(time.Now()),
395-
User: claims.UserInfo.Username,
398+
User: user.Username,
396399
Action: "Close/End Poll",
397400
}
398401
err = database.WriteAction(c, &action)
@@ -405,15 +408,15 @@ func ClosePoll(c *gin.Context) {
405408
}
406409

407410
// ProcessSimpleVote Parses a simple ballot, validates it, and sends it to the database
408-
func processSimpleVote(c *gin.Context, poll *database.Poll, pId primitive.ObjectID, claims cshAuth.CSHClaims) {
411+
func processSimpleVote(c *gin.Context, poll *database.Poll, pId primitive.ObjectID, user cshAuth.CSHUserInfo) {
409412
vote := database.SimpleVote{
410413
Id: "",
411414
PollId: pId,
412415
Option: c.PostForm("option"),
413416
}
414417
voter := database.Voter{
415418
PollId: pId,
416-
UserId: claims.UserInfo.Username,
419+
UserId: user.Username,
417420
}
418421

419422
if hasOption(poll, c.PostForm("option")) {
@@ -428,15 +431,15 @@ func processSimpleVote(c *gin.Context, poll *database.Poll, pId primitive.Object
428431
}
429432

430433
// ProcessRankedVote Parses the ranked choice ballot, validates it, and then sends it to the database
431-
func processRankedVote(c *gin.Context, poll *database.Poll, pId primitive.ObjectID, claims cshAuth.CSHClaims) {
434+
func processRankedVote(c *gin.Context, poll *database.Poll, pId primitive.ObjectID, user cshAuth.CSHUserInfo) {
432435
vote := database.RankedVote{
433436
Id: "",
434437
PollId: pId,
435438
Options: make(map[string]int),
436439
}
437440
voter := database.Voter{
438441
PollId: pId,
439-
UserId: claims.UserInfo.Username,
442+
UserId: user.Username,
440443
}
441444

442445
// Populate vote
@@ -544,8 +547,8 @@ func canVote(user cshAuth.CSHUserInfo, poll database.Poll, allowedUsers []string
544547
}
545548

546549
// ownsPoll Returns whether a user is the owner of a particular poll
547-
func ownsPoll(poll *database.Poll, claims cshAuth.CSHClaims) bool {
548-
return poll.CreatedBy == claims.UserInfo.Username
550+
func ownsPoll(poll *database.Poll, user cshAuth.CSHUserInfo) bool {
551+
return poll.CreatedBy == user.Username
549552
}
550553

551554
func uniquePolls(polls []*database.Poll) []*database.Poll {

eboard.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@ func HandleGetEboardVote(c *gin.Context) {
2323
if votes == nil {
2424
votes = make(map[string]float32)
2525
}
26-
if voters == nil {
27-
voters = []string{}
28-
}
29-
fmt.Println(votes)
26+
fmt.Println(user)
3027
c.HTML(http.StatusOK, "eboard.tmpl", gin.H{
31-
"Username": user,
28+
"Username": user.Username,
29+
"EBoard": IsEboard(user),
3230
"Voted": slices.Contains(voters, user.Username),
3331
"Results": votes,
3432
"VoteCount": len(voters),

0 commit comments

Comments
 (0)