Split checkout widget into separate components
This commit is contained in:
@@ -1,132 +0,0 @@
|
||||
package webcontroller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Form is a form which can be rendered in HTML and submitted
|
||||
type Form struct {
|
||||
// Name of the form. When this form is submitted this name will be in the `form` parameter
|
||||
Name string
|
||||
|
||||
Title string // Shown in a large font above the form
|
||||
PreFormHTML template.HTML // Content to be rendered above the form
|
||||
|
||||
Fields []Field
|
||||
|
||||
SubmitLabel string // Label for the submit button
|
||||
SubmitRed bool // If the submit button should be red or green
|
||||
|
||||
PostFormHTML template.HTML // Content to be rendered below the form
|
||||
|
||||
// Fields to render if the form has been submitted once
|
||||
Submitted bool // If the form has been submitted
|
||||
SubmitSuccess bool // If the submission was a success
|
||||
SubmitMessages []template.HTML // Messages telling the user the results
|
||||
|
||||
// Used for letting the browser know which user is logged in
|
||||
Username string
|
||||
|
||||
// Actions to perform when the form is rendered
|
||||
Extra ExtraActions
|
||||
}
|
||||
|
||||
// Field is a single input field in a form
|
||||
type Field struct {
|
||||
// Used for reading the data. Entered data is POSTed back to the same URL with this name
|
||||
Name string
|
||||
|
||||
// Is entered in the input field by default. If this is empty when running
|
||||
// Form.ReadInput() it will be set to the value entered by the user
|
||||
DefaultValue string
|
||||
|
||||
// The value entered by the user. Filled in when running Form.ReadInput()
|
||||
EnteredValue string
|
||||
|
||||
// Text next to the input field
|
||||
Label string
|
||||
|
||||
// Text below the input field
|
||||
Description template.HTML
|
||||
|
||||
Type FieldType
|
||||
|
||||
// Only used when Type == FieldTypeCaptcha
|
||||
CaptchaSiteKey string
|
||||
|
||||
// Only used when Type == FieldTypeRadio
|
||||
RadioValues []string
|
||||
}
|
||||
|
||||
// ExtraActions contains extra actions to performs when rendering the form
|
||||
type ExtraActions struct {
|
||||
// Redirects the browser to a different URL with a HTTP 303: See Other
|
||||
// status. This is useful for redirecting the user to a different page if
|
||||
// the form submission was successful
|
||||
RedirectTo string
|
||||
|
||||
// A cookie to install in the browser when the form is rendered. Useful for
|
||||
// setting / destroying user sessions or configurations
|
||||
SetCookie *http.Cookie
|
||||
}
|
||||
|
||||
// FieldType defines the type a form field has and how it should be rendered
|
||||
type FieldType string
|
||||
|
||||
// Fields which can be in a form
|
||||
const (
|
||||
FieldTypeText FieldType = "text"
|
||||
FieldTypeTextarea FieldType = "textarea"
|
||||
FieldTypeNumber FieldType = "number"
|
||||
FieldTypeUsername FieldType = "username"
|
||||
FieldTypeEmail FieldType = "email"
|
||||
FieldTypeRadio FieldType = "radio"
|
||||
FieldTypeCurrentPassword FieldType = "current-password"
|
||||
FieldTypeNewPassword FieldType = "new-password"
|
||||
FieldTypeCaptcha FieldType = "captcha"
|
||||
FieldTypeDescription FieldType = "description"
|
||||
)
|
||||
|
||||
// ReadInput reads the form of a request and fills in the values for each field.
|
||||
// The return value will be true if this form was submitted and false if the
|
||||
// form was not submitted
|
||||
func (f *Form) ReadInput(r *http.Request) (success bool) {
|
||||
if r.FormValue("form") != f.Name {
|
||||
f.Submitted = false
|
||||
return false
|
||||
}
|
||||
f.Submitted = true
|
||||
|
||||
for i, field := range f.Fields {
|
||||
// Remove carriage returns
|
||||
field.EnteredValue = strings.ReplaceAll(r.FormValue(field.Name), "\r", "")
|
||||
|
||||
if field.EnteredValue != "" {
|
||||
field.DefaultValue = field.EnteredValue
|
||||
}
|
||||
|
||||
if field.Type == FieldTypeCaptcha && field.EnteredValue == "" {
|
||||
field.EnteredValue = r.FormValue("g-recaptcha-response")
|
||||
}
|
||||
|
||||
f.Fields[i] = field // Update the new values in the array
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FieldVal is a utility function for getting the entered value of a field by
|
||||
// its name. By using this function you don't have to use nondescriptive array
|
||||
// indexes to get the values. It panics if the field name is not found in the
|
||||
// form
|
||||
func (f *Form) FieldVal(name string) (enteredValue string) {
|
||||
for _, field := range f.Fields {
|
||||
if field.Name == name {
|
||||
return field.EnteredValue
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("FieldVal called on unregistered field name '%s'", name))
|
||||
}
|
@@ -35,9 +35,6 @@ type TemplateData struct {
|
||||
|
||||
Other interface{}
|
||||
URLQuery url.Values
|
||||
|
||||
// Only used for pages containing forms
|
||||
Form Form
|
||||
}
|
||||
|
||||
func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) (t *TemplateData) {
|
||||
|
@@ -324,71 +324,6 @@ func (wc *WebController) serveFile(path string) httprouter.Handle {
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveForm(
|
||||
handler func(*TemplateData, *http.Request) Form,
|
||||
opts handlerOpts,
|
||||
) httprouter.Handle {
|
||||
return func(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
p httprouter.Params,
|
||||
) {
|
||||
if opts.NoEmbed {
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
}
|
||||
|
||||
var td = wc.newTemplateData(w, r)
|
||||
if opts.Auth && !td.Authenticated {
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// The handler retuns the form which will be rendered
|
||||
td.Form = handler(td, r)
|
||||
td.Title = td.Form.Title
|
||||
td.Form.Username = td.User.Username
|
||||
|
||||
// Execute the extra actions if any
|
||||
if td.Form.Extra.SetCookie != nil {
|
||||
w.Header().Del("Set-Cookie")
|
||||
http.SetCookie(w, td.Form.Extra.SetCookie)
|
||||
}
|
||||
if td.Form.Extra.RedirectTo != "" {
|
||||
http.Redirect(w, r, td.Form.Extra.RedirectTo, http.StatusSeeOther)
|
||||
log.Debug("redirect: %s", td.Form.Extra.RedirectTo)
|
||||
return // Don't need to render a form if the user is redirected
|
||||
}
|
||||
|
||||
// Remove the recaptcha field if captcha is disabled
|
||||
if wc.captchaKey() == "none" {
|
||||
for i, field := range td.Form.Fields {
|
||||
if field.Type == FieldTypeCaptcha {
|
||||
td.Form.Fields = append(
|
||||
td.Form.Fields[:i],
|
||||
td.Form.Fields[i+1:]...,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the entered values if the request was successful
|
||||
if td.Form.SubmitSuccess {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
for i, field := range td.Form.Fields {
|
||||
field.EnteredValue = ""
|
||||
td.Form.Fields[i] = field
|
||||
}
|
||||
} else if td.Form.Submitted {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
err := wc.templates.Run(w, r, "form_page", td)
|
||||
if err != nil && !util.IsNetError(err) {
|
||||
log.Error("Error executing form page: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *WebController) serveForbidden(w http.ResponseWriter, r *http.Request) {
|
||||
log.Debug("Forbidden: %s", r.URL)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
|
Reference in New Issue
Block a user