added the E-mail address validation form

This commit is contained in:
2025-10-04 15:13:00 -06:00
parent c7f5c57e82
commit 070afc365e
7 changed files with 242 additions and 3 deletions
+42
View File
@@ -14,6 +14,8 @@ import (
"embed"
"fmt"
"net/mail"
"strconv"
"strings"
"git.erbosoft.com/amy/amsterdam/database"
"gopkg.in/yaml.v3"
@@ -95,6 +97,17 @@ func (fld *DialogItem) IsChecked() bool {
return false
}
// ValueRange returns the minimum and maximum values for an integer field.
func (fld *DialogItem) ValueRange() (int, int) {
if fld.Type == "integer" && fld.Param != "" {
parms := strings.Split(fld.Param, "-")
low, _ := strconv.Atoi(parms[0])
high, _ := strconv.Atoi(parms[1])
return low, high
}
return -1, -1
}
/* Field returns a pointer to a dialog's field, given its name.
* Parameters:
* name - The name of the field to find.
@@ -259,6 +272,34 @@ func validateTextField(fld *DialogItem) error {
return nil
}
/* validateIntegerField validates an integer field.
* Parameters:
* fld - The field to be validated.
* Returns:
* Standard Go error status.
*/
func validateIntegerField(fld *DialogItem) error {
err := validateTextField(fld)
if err == nil {
var v int
v, err = strconv.Atoi(fld.Value)
if err == nil {
fld.AuxData = v // cache parsed value
lo, hi := fld.ValueRange()
if lo != -1 && hi != -1 {
if v < lo {
return fmt.Errorf("value of field \"%s\" cannot be less than %d", fld.Caption, lo)
} else if v > hi {
return fmt.Errorf("value of field \"%s\" cannot be greater than %d", fld.Caption, hi)
}
}
} else {
return fmt.Errorf("value of field \"%s\" is not a valid integer", fld.Caption)
}
}
return nil
}
/* validateAmsIdField validates an Amsterdam ID field.
* Parameters:
* fld - The field to be validated.
@@ -339,6 +380,7 @@ var validators = map[string]validatorFunc{
"email": validateEmailField,
"header": nilValidator,
"hidden": nilValidator,
"integer": validateIntegerField,
"password": validateTextField,
"text": validateTextField,
}
+39
View File
@@ -0,0 +1,39 @@
#
# Amsterdam Web Communities System
# Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
name: "verify"
formName: "verifyform"
menuSelector: "top"
title: "Verify E-mail Address"
action: "/verify"
instructions: >
Check your E-mail, then enter the confirmation number that was E-mailed to you in the field below.
(The E-mail might take a few minutes or so to get to you, so be patient.) Once you do so, your account
will be fully validated. If you have not received your confirmation within a few minutes, click on the
<b>Send Again</b> button below.
fields:
- type: "hidden"
name: "tgt"
value: ""
- type: "integer"
name: "num"
caption: "Confirmation Number"
size: 7
param: "1000000-9999999"
- type: "button"
name: "ok"
caption: "OK"
param: "blue"
- type: "button"
name: "sendagain"
caption: "Send Again"
param: "gray"
- type: "button"
name: "cancel"
caption: "Cancel"
param: "red"
+6
View File
@@ -13,6 +13,7 @@ package ui
import (
"fmt"
"net/http"
"net/url"
"git.erbosoft.com/amy/amsterdam/config"
"git.erbosoft.com/amy/amsterdam/database"
@@ -99,6 +100,11 @@ func AmWrap(myfunc func(AmContext) (string, any, error)) echo.HandlerFunc {
} else {
log.Warnf("unable to rotate login cookie: %v", cerr)
}
if !user.VerifyEMail {
// bounce to E-mail verification before we go anywhere
return sendPageData(ctxt, amctxt, "redirect",
"/verify?tgt="+url.PathEscape(ctxt.Request().URL.Path))
}
} else {
log.Errorf("login cookie bogus, do not use: %v", cerr)
amctxt.ClearLoginCookie()
+16
View File
@@ -67,6 +67,22 @@
value="{{ .Value }}"
class="flex-1 px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
</div>
{{ else if .Type == "integer" }}
<div class="flex items-center">
<label for="{{ .Name }}" class="w-64 text-right pr-4 text-black text-sm">
{{ .Caption }}{{ if .Subcaption != "" }} {{ .Subcaption }}{{ end }}:
{{ if .Required }}<span class="text-red-600">*</span>{{ end }}
</label>
<input type="text" id="{{ .Name }}" name="{{ .Name }}"
{{ if .Size > 0 }}size="{{ .Size }}"{{ end }}
{{ if .MaxLength > 0 }}maxlength="{{ .MaxLength }}"{{ end }}
value="{{ .Value }}"
class="flex-1 px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{{ lo, hi := .ValueRange() }}
{{ if lo != -1 && hi != -1 }}
<span class="text-sm">({{ lo }}-{{ hi }})</span>
{{ end }}
</div>
{{ else if .Type == "password" }}
<div class="flex items-center">
<label for="{{ .Name }}" class="w-64 text-right pr-4 text-black text-sm">