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