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") } 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, }) }