Implement database mapping for vote types

main
Jan Dittberner 2 years ago
parent e1af6876c1
commit aa3a1b0cc7

@ -100,7 +100,9 @@ func parseConfig(configFile string) (*Config, error) {
}
if len(config.CsrfKey) != csrfKeyLength {
return nil, fmt.Errorf("CSRF key must be exactly %d bytes long but is %d bytes long", csrfKeyLength, len(config.CsrfKey))
return nil, fmt.Errorf(
"CSRF key must be exactly %d bytes long but is %d bytes long", csrfKeyLength, len(config.CsrfKey),
)
}
return config, nil

@ -29,12 +29,13 @@ import (
"strings"
"time"
"git.cacert.org/cacert-boardvoting/internal/models"
"git.cacert.org/cacert-boardvoting/internal/validator"
"git.cacert.org/cacert-boardvoting/ui"
"github.com/Masterminds/sprig/v3"
"github.com/gorilla/csrf"
"github.com/julienschmidt/httprouter"
"git.cacert.org/cacert-boardvoting/internal/models"
"git.cacert.org/cacert-boardvoting/internal/validator"
"git.cacert.org/cacert-boardvoting/ui"
)
func newTemplateCache() (map[string]*template.Template, error) {
@ -295,12 +296,36 @@ func (app *application) newMotionSubmit(w http.ResponseWriter, r *http.Request)
return
}
form.CheckField(validator.NotBlank(form.Title), "title", "This field cannot be blank")
form.CheckField(validator.MinChars(form.Title, minimumTitleLength), "title", fmt.Sprintf("This field must be at least %d characters long", minimumTitleLength))
form.CheckField(validator.MaxChars(form.Title, maximumTitleLength), "title", fmt.Sprintf("This field must be at most %d characters long", maximumTitleLength))
form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank")
form.CheckField(validator.MinChars(form.Content, minimumContentLength), "content", fmt.Sprintf("This field must be at least %d characters long", minimumContentLength))
form.CheckField(validator.MaxChars(form.Content, maximumContentLength), "content", fmt.Sprintf("This field must be at most %d characters long", maximumContentLength))
form.CheckField(
validator.NotBlank(form.Title),
"title",
"This field cannot be blank",
)
form.CheckField(
validator.MinChars(form.Title, minimumTitleLength),
"title",
fmt.Sprintf("This field must be at least %d characters long", minimumTitleLength),
)
form.CheckField(
validator.MaxChars(form.Title, maximumTitleLength),
"title",
fmt.Sprintf("This field must be at most %d characters long", maximumTitleLength),
)
form.CheckField(
validator.NotBlank(form.Content),
"content",
"This field cannot be blank",
)
form.CheckField(
validator.MinChars(form.Content, minimumContentLength),
"content",
fmt.Sprintf("This field must be at least %d characters long", minimumContentLength),
)
form.CheckField(
validator.MaxChars(form.Content, maximumContentLength),
"content",
fmt.Sprintf("This field must be at most %d characters long", maximumContentLength),
)
form.CheckField(validator.PermittedStr(
form.Due,
"+3 days",

@ -41,6 +41,8 @@ import (
"git.cacert.org/cacert-boardvoting/internal/models"
)
const sessionHours = 12
var (
version = "undefined"
commit = "undefined"
@ -95,7 +97,7 @@ func main() {
sessionManager := scs.New()
sessionManager.Store = sqlite3store.New(db.DB)
sessionManager.Lifetime = 12 * time.Hour
sessionManager.Lifetime = sessionHours * time.Hour
app := &application{
errorLog: errorLog,
@ -145,7 +147,12 @@ func setupFormDecoder() *form.Decoder {
decoder := form.NewDecoder()
decoder.RegisterCustomTypeFunc(func(values []string) (interface{}, error) {
return models.VoteTypeFromString(values[0])
v, err := models.VoteTypeFromString(values[0])
if err != nil {
return nil, fmt.Errorf("could not convert value %s: %w", values[0], err)
}
return v, nil
}, new(models.VoteType))
return decoder

@ -20,6 +20,7 @@ package models
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"log"
@ -55,9 +56,9 @@ func VoteTypeFromString(label string) (*VoteType, error) {
return nil, fmt.Errorf("unknown vote type %s", label)
}
func VoteTypeFromUint8(id uint8) (*VoteType, error) {
func VoteTypeFromInt(id int64) (*VoteType, error) {
for _, vt := range []*VoteType{VoteTypeMotion, VoteTypeVeto} {
if vt.id == id {
if int64(vt.id) == id {
return vt, nil
}
}
@ -65,6 +66,26 @@ func VoteTypeFromUint8(id uint8) (*VoteType, error) {
return nil, fmt.Errorf("unknown vote type id %d", id)
}
func (v *VoteType) Scan(src any) error {
value, ok := src.(int64)
if !ok {
return fmt.Errorf("could not cast %v of %T to uint8", src, src)
}
vt, err := VoteTypeFromInt(value)
if err != nil {
return err
}
*v = *vt
return nil
}
func (v *VoteType) Value() (driver.Value, error) {
return int64(v.id), nil
}
func (v *VoteType) QuorumAndMajority() (int, float32) {
const (
majorityDefault = 0.99
@ -162,7 +183,7 @@ type Motion struct {
Due time.Time
Modified time.Time
Tag string
VoteType VoteType
VoteType *VoteType
}
type ClosedMotion struct {
@ -180,7 +201,7 @@ type MotionModel struct {
func (m *MotionModel) Create(
ctx context.Context,
proponent *Voter,
voteType VoteType,
voteType *VoteType,
title, content string,
proposed, due time.Time,
) (int64, error) {
@ -400,7 +421,7 @@ type MotionForDisplay struct {
Proposed time.Time
Title string
Content string
Type VoteType `db:"votetype"`
Type *VoteType `db:"votetype"`
Status VoteStatus
Due time.Time
Modified time.Time

@ -1,3 +1,20 @@
/*
Copyright 2022 CAcert Inc.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validator
import (
@ -41,16 +58,6 @@ func MinChars(value string, n int) bool {
return utf8.RuneCountInString(value) >= n
}
func PermittedInt(value int, permittedValues ...int) bool {
for i := range permittedValues {
if value == permittedValues[i] {
return true
}
}
return false
}
func PermittedStr(value string, permittedValues ...string) bool {
for i := range permittedValues {
if value == permittedValues[i] {

Loading…
Cancel
Save