🎉🚀 May the concensus be with us!

This commit is contained in:
Brian Wiborg 2024-05-13 00:47:24 +02:00
commit 48328e7db2
No known key found for this signature in database
GPG key ID: BE53FA9286B719D6
33 changed files with 4051 additions and 0 deletions

137
http/main.go Normal file
View file

@ -0,0 +1,137 @@
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,
})
}

31
http/template_renderer.go Normal file
View file

@ -0,0 +1,31 @@
package http
import (
"io"
"text/template"
"github.com/labstack/echo"
)
type Template struct {
Templates *template.Template
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return t.Templates.ExecuteTemplate(w, name, data)
}
func NewTemplateRenderer(e *echo.Echo, paths ...string) {
tmpl := &template.Template{}
for i := range paths {
template.Must(tmpl.ParseGlob(paths[i]))
}
t := newTemplate(tmpl)
e.Renderer = t
}
func newTemplate(templates *template.Template) echo.Renderer {
return &Template{
Templates: templates,
}
}