switching form bindings/validation and redirecting to proper 500 page
This commit is contained in:
parent
875b71b504
commit
de64cd6aab
6 changed files with 72 additions and 56 deletions
2
go.mod
2
go.mod
|
@ -6,6 +6,7 @@ require (
|
||||||
github.com/antchfx/htmlquery v1.2.5
|
github.com/antchfx/htmlquery v1.2.5
|
||||||
github.com/gin-contrib/multitemplate v0.0.0-20220705015713-e21a0ba39de3
|
github.com/gin-contrib/multitemplate v0.0.0-20220705015713-e21a0ba39de3
|
||||||
github.com/gin-gonic/gin v1.8.1
|
github.com/gin-gonic/gin v1.8.1
|
||||||
|
github.com/go-playground/validator/v10 v10.11.0
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||||
github.com/spf13/viper v1.12.0
|
github.com/spf13/viper v1.12.0
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||||
|
@ -19,7 +20,6 @@ require (
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.0 // indirect
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.11.0 // indirect
|
|
||||||
github.com/goccy/go-json v0.9.10 // indirect
|
github.com/goccy/go-json v0.9.10 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
|
41
main.go
41
main.go
|
@ -38,17 +38,12 @@ func (web Web) newWatch(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) createWatch(c *gin.Context) {
|
func (web Web) createWatch(c *gin.Context) {
|
||||||
interval, err := strconv.Atoi(c.PostForm("interval"))
|
var watch Watch
|
||||||
|
errMap, err := bindAndValidateWatch(&watch, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
c.HTML(http.StatusBadRequest, "500", errMap)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
web.db.Create(&watch)
|
||||||
watch := &Watch{
|
|
||||||
Name: c.PostForm("name"),
|
|
||||||
Interval: interval,
|
|
||||||
}
|
|
||||||
web.db.Create(watch)
|
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch.ID))
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,29 +67,15 @@ func (web Web) viewWatch(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) createURL(c *gin.Context) {
|
func (web Web) createURL(c *gin.Context) {
|
||||||
watch_id, err := strconv.ParseUint(c.PostForm("watch_id"), 10, 64)
|
var url URL
|
||||||
|
errMap, err := bindAndValidateURL(&url, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
log.Print(err)
|
||||||
return // TODO response
|
c.HTML(http.StatusInternalServerError, "500", errMap)
|
||||||
}
|
|
||||||
name := c.PostForm("name")
|
|
||||||
if name == "" {
|
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
url := c.PostForm("url")
|
web.db.Create(url)
|
||||||
if url == "" {
|
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", url.WatchID))
|
||||||
c.Redirect(http.StatusSeeOther, "/watch/new")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
url_model := &URL{
|
|
||||||
WatchID: uint(watch_id),
|
|
||||||
Name: name,
|
|
||||||
URL: url,
|
|
||||||
}
|
|
||||||
web.db.Create(url_model)
|
|
||||||
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/watch/view/%d", watch_id))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web Web) createQuery(c *gin.Context) {
|
func (web Web) createQuery(c *gin.Context) {
|
||||||
|
@ -253,6 +234,8 @@ func main() {
|
||||||
templates.AddFromFiles("newWatch", "templates/base.html", "templates/newWatch.html")
|
templates.AddFromFiles("newWatch", "templates/base.html", "templates/newWatch.html")
|
||||||
templates.AddFromFiles("viewWatch", "templates/base.html", "templates/viewWatch.html")
|
templates.AddFromFiles("viewWatch", "templates/base.html", "templates/viewWatch.html")
|
||||||
templates.AddFromFiles("editQuery", "templates/base.html", "templates/editQuery.html")
|
templates.AddFromFiles("editQuery", "templates/base.html", "templates/editQuery.html")
|
||||||
|
|
||||||
|
templates.AddFromFiles("500", "templates/base.html", "templates/500.html")
|
||||||
router.HTMLRender = templates
|
router.HTMLRender = templates
|
||||||
|
|
||||||
router.GET("/", web.index)
|
router.GET("/", web.index)
|
||||||
|
|
30
models.go
30
models.go
|
@ -6,36 +6,36 @@ import (
|
||||||
|
|
||||||
type Watch struct {
|
type Watch struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string
|
Name string `form:"name" yaml:"name" binding:"required" validate:"min=1"`
|
||||||
Interval int
|
Interval int `form:"interval" yaml:"interval" binding:"required"`
|
||||||
URLs []URL
|
URLs []URL
|
||||||
}
|
}
|
||||||
|
|
||||||
type URL struct {
|
type URL struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
WatchID uint
|
WatchID uint `form:"watch_id" yaml:"watch_id" binding:"required"`
|
||||||
Watch Watch
|
Watch *Watch `form:"watch" yaml:"watch" validate:"omitempty"`
|
||||||
Name string
|
Name string `form:"name" yaml:"name" binding:"required"`
|
||||||
URL string
|
URL string `form:"url" yaml:"url" binding:"required,url"`
|
||||||
Queries []Query
|
Queries []Query
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
URLID uint
|
URLID uint `form:"url_id" yaml:"url_id" binding:"required"`
|
||||||
URL URL
|
URL URL
|
||||||
Name string
|
Name string `form:"name" yaml:"name" binding:"required"`
|
||||||
Type string
|
Type string `form:"type" yaml:"type" binding:"required"`
|
||||||
Query string
|
Query string `form:"query" yaml:"query" binding:"required"`
|
||||||
Filters []Filter
|
Filters []Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
QueryID uint
|
QueryID uint `form:"query_id" yaml:"query_id" binding:"required"`
|
||||||
Query Query
|
Query Query
|
||||||
Name string
|
Name string `form:"name" yaml:"name" binding:"required"`
|
||||||
Type string
|
Type string `form:"type" yaml:"type" binding:"required"`
|
||||||
From string
|
From string `form:"from" yaml:"from" binding:"required"`
|
||||||
To string
|
To string `form:"to" yaml:"to" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
3
templates/500.html
Normal file
3
templates/500.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{{define "content"}}
|
||||||
|
<h1>Something went wrong, try again.</h1>
|
||||||
|
{{end}}
|
|
@ -1,12 +1,3 @@
|
||||||
{{template "base" .}}
|
|
||||||
{{define "title"}}
|
|
||||||
{{end}}
|
|
||||||
{{define "navbar"}}
|
|
||||||
{{end}}
|
|
||||||
{{define "head"}}
|
|
||||||
{{end}}
|
|
||||||
{{define "left"}}
|
|
||||||
{{end}}
|
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<form action="/watch/create" method="post">
|
<form action="/watch/create" method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
@ -19,6 +10,5 @@
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-primary mb-3" value="Create">
|
<input type="submit" class="btn btn-primary mb-3" value="Create">
|
||||||
</form>
|
</form>
|
||||||
{{end}}
|
{{ . }}
|
||||||
{{define "right"}}
|
|
||||||
{{end}}
|
{{end}}
|
40
util.go
Normal file
40
util.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bindAndValidateWatch(watch *Watch, c *gin.Context) (map[string]string, error) {
|
||||||
|
err := c.ShouldBind(watch)
|
||||||
|
return validate(err), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindAndValidateURL(url *URL, c *gin.Context) (map[string]string, error) {
|
||||||
|
err := c.ShouldBind(url)
|
||||||
|
return validate(err), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func prettyError(fieldError validator.FieldError) string {
|
||||||
|
switch fieldError.Tag() {
|
||||||
|
case "required":
|
||||||
|
return fieldError.Field() + " is required"
|
||||||
|
default:
|
||||||
|
return "No prettyError for " + fieldError.Tag()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(err error) map[string]string {
|
||||||
|
out := make(map[string]string)
|
||||||
|
if err != nil {
|
||||||
|
var ve validator.ValidationErrors
|
||||||
|
if errors.As(err, &ve) {
|
||||||
|
for _, fe := range ve {
|
||||||
|
out[fe.Field()] = prettyError(fe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue