govote/http/main.go

138 lines
3.5 KiB
Go
Raw Normal View History

2024-05-12 22:47:24 +00:00
package http
import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
"code.c-base.org/baccenfutter/govote/store"
"code.c-base.org/baccenfutter/govote/utils"
"code.c-base.org/baccenfutter/govote/voting"
"code.c-base.org/baccenfutter/govote/voting/quorum"
"code.c-base.org/baccenfutter/govote/voting/threshold"
"code.c-base.org/baccenfutter/govote/voting/vote"
"github.com/google/uuid"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func Serve(bindAddr string) error {
e := echo.New()
e.Pre(middleware.RemoveTrailingSlash())
// e.Use(middleware.Recover())
NewTemplateRenderer(e, "tmpl/*.html")
e.Static("/static", "static")
e.GET("/", handleIndex)
e.GET("/v", handleVotingForm)
e.POST("/v", handleNewVoting)
e.GET("/v/:id", handleShowVoting)
e.POST("/v/:id", handleVote)
return e.Start(bindAddr)
}
func handleIndex(ctx echo.Context) error {
// return ctx.Redirect(http.StatusTemporaryRedirect, "/v")
return ctx.String(200, ctx.Request().Header.Get("X-Remote-User"))
}
func handleNewVoting(ctx echo.Context) error {
id :=utils.GenerateRandomString(11)
var (
formReferendum = ctx.FormValue("referendum")
formDeadline = ctx.FormValue("deadline")
formQuorum = ctx.FormValue("quorum")
formThreshold = ctx.FormValue("threshold")
formElectors = ctx.FormValue("electors")
formAnonymous = ctx.FormValue("anonymous")
)
var (
err error
r string
d time.Time
q quorum.Quorum
t threshold.Threshold
e = []string{}
a bool
)
r = formReferendum
deadlineNum := fmt.Sprintf("%s", formDeadline[:len(formDeadline)-1])
deadlineUnit := fmt.Sprintf("%s", formDeadline[len(formDeadline)-1:])
deadlineInt, err := strconv.Atoi(deadlineNum)
if err != nil {
return err
}
switch deadlineUnit {
case "m", "":
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Minute).Round(time.Second)
case "h":
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Hour).Round(time.Second)
case "d":
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Hour*24).Round(time.Second)
default:
panic("this code should never be reached")
}
if q, err = quorum.FromString(formQuorum); err != nil {
return err
}
if t, err = threshold.FromString(formThreshold); err != nil {
return err
}
e = strings.Split(formElectors, " ")
if formAnonymous == "on" {
a = true
}
store.NewVoting(id, r, d, q, t, e, a)
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/v/%s", id))
}
func handleVotingForm(ctx echo.Context) error {
return ctx.Render(http.StatusOK, "voting_form", nil)
}
func handleVote(ctx echo.Context) error {
var (
id = uuid.New().String()
vid = ctx.Param("id")
elector = ctx.Request().Header.Get("X-Remote-User")
choice = ctx.FormValue("vote")
v *voting.Voting
c vote.Choice
err error
)
v, err = store.GetVoting(vid)
if err != nil {
return err
}
if time.Now().UTC().After(v.Deadline()) {
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/v/%s", vid))
}
if c, err = vote.ChoiceFromString(choice); err != nil {
return err
}
store.PlaceVote(id, vid, elector, c)
return ctx.Render(http.StatusFound, "thanks", map[string]interface{}{
"Id": id,
"Vid": vid,
})
}
func handleShowVoting(ctx echo.Context) error {
v, err := store.GetVoting(ctx.Param("id"))
if err != nil {
fmt.Println(err)
return err
}
return ctx.Render(http.StatusOK, "voting", map[string]interface{}{
"Voting": v,
})
}