commit 92910c7f03a60e9863bae960c14549aa96c263e8
parent 24faf45f89cd0f1c73389639f2d8c2d397c975e7
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Wed, 1 May 2024 14:44:45 +0200
Fix HAN a11y issue 4: Button under QR code removed. Also automatic redirects after payment to registration page.
Diffstat:
3 files changed, 156 insertions(+), 83 deletions(-)
diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go
@@ -516,6 +516,10 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Unauthorized", http.StatusSeeOther)
return
}
+ if !regMetadata.Paid {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "/buy/payment?token=" + regMetadata.RegistrationID, http.StatusSeeOther)
+ return;
+ }
for _, record := range namestoreResponse.Records {
if isDelegationRecordType(record.RecordType) {
value = record.Value
@@ -545,13 +549,102 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) {
return
}
-func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
+func (t *Registrar) paymentPage(w http.ResponseWriter, r *http.Request) {
var (
namestoreResponse NamestoreRecord
regMetadata *RegistrationMetadata
client *http.Client
label string
errorMsg string
+ )
+ vars := mux.Vars(r)
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ client = &http.Client{}
+ label = vars["label"]
+ sanitizedLabel := url.QueryEscape(vars["label"])
+ err := t.isNameValid(label)
+ if nil != err {
+ http.Redirect(w, r, fmt.Sprintf("/?error=%s", err), http.StatusSeeOther)
+ return
+ }
+ req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + sanitizedLabel + "?include_maintenance=yes", nil)
+ if t.GnunetBasicAuthEnabled {
+ req.SetBasicAuth(t.GnunetUsername, t.GnunetPassword)
+ }
+ resp, err := client.Do(req)
+ if err != nil {
+ http.Redirect(w, r, "/" + "?error=Registration failed: Failed to get zone contents", http.StatusSeeOther)
+ fmt.Printf("Failed to get zone contents")
+ return
+ }
+ defer resp.Body.Close()
+ if http.StatusOK == resp.StatusCode {
+ respData, err := io.ReadAll(resp.Body)
+ if err != nil {
+ http.Redirect(w, r, "/" + "?error=Registration failed: Failed to get zone contents", http.StatusSeeOther)
+ fmt.Printf("Failed to get zone contents" + err.Error())
+ return
+ }
+ err = json.NewDecoder(bytes.NewReader(respData)).Decode(&namestoreResponse)
+ if err != nil {
+ http.Redirect(w, r, "/" + "?error=Registration failed: Failed to get zone contents", http.StatusSeeOther)
+ fmt.Printf("Failed to get zone contents" + err.Error())
+ return
+ }
+ regMetadata, err = t.getCurrentRegistrationMetadata(sanitizedLabel, &namestoreResponse)
+ if err != nil {
+ http.Redirect(w, r, "/" + "?error=Registration failed: Failed to get registration metadata", http.StatusSeeOther)
+ fmt.Printf("Failed to get registration metadata" + err.Error())
+ return
+ }
+ } else if http.StatusNotFound != resp.StatusCode {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Payment failed: Error determining zone status", http.StatusSeeOther)
+ return
+ }
+ if nil == regMetadata {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Payment failed: Please try again.", http.StatusSeeOther)
+ return
+ }
+ if regMetadata.Paid {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Payment already paid.", http.StatusSeeOther)
+ return
+ }
+ _, payto, paytoErr := t.Merchant.IsOrderPaid(regMetadata.OrderID)
+ if paytoErr != nil {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Payment failed: Error getting payment data", http.StatusSeeOther)
+ return
+ }
+ qrPng, qrErr := qrcode.Encode(payto, qrcode.Medium, 256)
+ if qrErr != nil {
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error generating QR code", http.StatusSeeOther)
+ return
+ }
+ encodedPng := base64.StdEncoding.EncodeToString(qrPng)
+ cost, _ := t.RegistrationCost.FormatWithCurrencySpecification(t.CurrencySpec)
+ w.Header().Set("Refresh", "20;url=" + t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regMetadata.RegistrationID)
+ fullData := map[string]interface{}{
+ "qrCode": template.URL("data:image/png;base64," + encodedPng),
+ "payto": template.URL(payto),
+ "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regMetadata.RegistrationID),
+ "registrationId": regMetadata.RegistrationID,
+ "label": sanitizedLabel,
+ "error": errorMsg,
+ "cost": cost,
+ "suffixHint": t.SuffixHint,
+ }
+ err = t.BuyTpl.Execute(w, fullData)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return
+}
+
+func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
+ var (
+ namestoreResponse NamestoreRecord
+ regMetadata *RegistrationMetadata
+ client *http.Client
+ label string
regId string
)
vars := mux.Vars(r)
@@ -615,16 +708,11 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Unable to create order", http.StatusSeeOther)
return
}
- _, payto, paytoErr := t.Merchant.IsOrderPaid(orderID)
+ _, _, paytoErr := t.Merchant.IsOrderPaid(orderID)
if paytoErr != nil {
http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error getting payment data", http.StatusSeeOther)
return
}
- qrPng, qrErr := qrcode.Encode(payto, qrcode.Medium, 256)
- if qrErr != nil {
- http.Redirect(w, r, "/name/" + sanitizedLabel + "?error=Registration failed: Error generating QR code", http.StatusSeeOther)
- return
- }
paymentUntil := time.Now().Add(t.PaymentExpiration)
if nil != regMetadata {
var newZkeyRecord RecordData
@@ -661,22 +749,7 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
return
}
}
- encodedPng := base64.StdEncoding.EncodeToString(qrPng)
- cost, _ := t.RegistrationCost.FormatWithCurrencySpecification(t.CurrencySpec)
- fullData := map[string]interface{}{
- "qrCode": template.URL("data:image/png;base64," + encodedPng),
- "payto": template.URL(payto),
- "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regId),
- "registrationId": regId,
- "label": sanitizedLabel,
- "error": errorMsg,
- "cost": cost,
- "suffixHint": t.SuffixHint,
- }
- err = t.BuyTpl.Execute(w, fullData)
- if err != nil {
- fmt.Println(err)
- }
+ http.Redirect(w, r, "/name/" + sanitizedLabel + "/buy/payment?token=" + regId, http.StatusSeeOther)
return
}
@@ -877,6 +950,7 @@ func (t *Registrar) setupHandlers() {
t.Router.HandleFunc("/", t.landingPage).Methods("GET")
t.Router.HandleFunc("/name/{label}", t.namePage).Methods("GET")
t.Router.HandleFunc("/name/{label}/buy", t.buyPage).Methods("GET")
+ t.Router.HandleFunc("/name/{label}/buy/payment", t.paymentPage).Methods("GET")
t.Router.HandleFunc("/name/{label}/edit", t.editRegistration).Methods("GET")
t.Router.HandleFunc("/name/{label}/edit", t.updateRegistration).Methods("POST")
t.Router.HandleFunc("/search", t.searchPage).Methods("GET")
diff --git a/web/templates/buy.html b/web/templates/buy.html
@@ -14,13 +14,12 @@
<a class="link-dark" href="{{.payto}}" class="btn btn-success mb-3">Pay {{.cost}} with your Taler wallet</a><br/>
Alternatively, you can pay using your mobile wallet by scanning the QR code below:<br/>
- <a class="link-dark" href="{{.fulfillmentUrl}}">
- <img class="qr" src="{{.qrCode}}"/>
- </a><br/>
+ <img class="qr" src="{{.qrCode}}"/>
+ <br/>
</div>
<div class="alert alert-warning">
<h4>Important</h4>
- After you pay with a mobile wallet, please click on the QR code to finalize your registration or visit <a class="link-dark" href="{{.fulfillmentUrl}}">your registration management page</a>.
+ After you pay with a mobile wallet, you should be redirected automatically. If not, you can visit <a class="link-dark" href="{{.fulfillmentUrl}}">your registration management page</a> directly.
<br/>
Your unique registration identifier is <b>{{.registrationId}}</b>.
<br/>
diff --git a/web/templates/edit.html b/web/templates/edit.html
@@ -1,67 +1,67 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <!-- Required meta tags -->
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
- <link href="/css/bootstrap.min.css" rel="stylesheet">
- <title>Edit registration</title>
- </head>
- <body>
- {{if .error}}
- <div class="container pt-5">
- <div class="alert alert-danger" role="alert">
- <h4 class="alert-heading">Oh no!</h4>
- <hr>
- <p class="mb-0">{{.error}}.</p>
- </div>
+ <head>
+ <!-- Required meta tags -->
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <link href="/css/bootstrap.min.css" rel="stylesheet">
+ <title>Edit registration</title>
+ </head>
+ <body>
+ {{if .error}}
+ <div class="container pt-5">
+ <div class="alert alert-danger" role="alert">
+ <h4 class="alert-heading">Oh no!</h4>
+ <hr>
+ <p class="mb-0">{{.error}}.</p>
</div>
- {{end}}
- {{if eq .remainingDays 0}}
- <div class="container pt-5">
- <div class="alert alert-danger" role="alert">
- <h4 class="alert-heading">Registration inactive!</h4>
- <hr>
- <p class="mb-0">Your registration is not yet active. Have you completed the payment yet?</p>
- </div>
+ </div>
+ {{end}}
+ {{if eq .remainingDays 0}}
+ <div class="container pt-5">
+ <div class="alert alert-danger" role="alert">
+ <h4 class="alert-heading">Registration inactive!</h4>
+ <hr>
+ <p class="mb-0">Your registration is not yet active. Have you completed the payment yet?</p>
</div>
- {{end}}
- <div class="container pt-5">
- <h1 class="mb-5">Manage registration for <i class="text-primary">{{.label}}</i></h1>
- <form action="/name/{{.label}}/edit" method="post" class="align-items-center mb-5">
- <div class="row">
- <div class="col-md-12 alert alert-light">
- <h4>Zone information</h4>
- <input type="hidden" value="{{.token}}" name="token">
- {{if ne .remainingDays 0}}
- <div class="form-floating mb-3">
- <input name="zkey" id="zkeyInput" class="form-control" value="{{.zkey}}" maxlength="63" type="text" placeholder="Enter your zone key here!" required autofocus>
- <label for="zkeyInput">Enter your PKEY or EDKEY here</label>
- </div>
- <input class="btn btn-primary" type="submit" value="Update zone key">
- {{else}}
- <div class="form-floating mb-3">
- <input name="zkey" id="zkeyInput" class="form-control" value="{{.zkey}}" disabled="true" maxlength="63" type="text" placeholder="Enter your zone key here!" required autofocus>
- <label for="zkeyInput">Enter your PKEY or EDKEY here</label>
- </div>
- {{end}}
- </div>
- </div>
- </form>
- {{if ne .remainingDays 0}}
- <div class="row mt-1">
+ </div>
+ {{end}}
+ <div class="container pt-5">
+ <h1 class="mb-5">Manage registration for <i class="text-primary">{{.label}}</i></h1>
+ <form action="/name/{{.label}}/edit" method="post" class="align-items-center mb-5">
+ <div class="row">
<div class="col-md-12 alert alert-light">
- <h4>Extension</h4>
+ <h4>Zone information</h4>
+ <input type="hidden" value="{{.token}}" name="token">
+ {{if ne .remainingDays 0}}
<div class="form-floating mb-3">
- <input disabled="true" id="expInput" class="form-control" value="{{.registeredUntil}}" type="text" required autofocus>
- <label for="expInput">Registration expires in {{.remainingDays}} days:</label>
+ <input name="zkey" id="zkeyInput" class="form-control" value="{{.zkey}}" maxlength="63" type="text" placeholder="Enter your zone key here!" required autofocus>
+ <label for="zkeyInput">Enter your PKEY or EDKEY here</label>
</div>
- <a class="btn btn-primary" href="/name/{{.label}}/buy">Extend registration for {{.extensionDaysCount}} days until <b>{{.extendedExpiration}}</b> for <b>{{.cost}}</b></a>
+ <input class="btn btn-primary" type="submit" value="Update zone key">
+ {{else}}
+ <div class="form-floating mb-3">
+ <input name="zkey" id="zkeyInput" class="form-control" value="{{.zkey}}" disabled="true" maxlength="63" type="text" placeholder="Enter your zone key here!" required autofocus>
+ <label for="zkeyInput">Enter your PKEY or EDKEY here</label>
+ </div>
+ {{end}}
+ </div>
+ </div>
+ </form>
+ {{if ne .remainingDays 0}}
+ <div class="row mt-1">
+ <div class="col-md-12 alert alert-light">
+ <h4>Extension</h4>
+ <div class="form-floating mb-3">
+ <input disabled="true" id="expInput" class="form-control" value="{{.registeredUntil}}" type="text" required autofocus>
+ <label for="expInput">Registration expires in {{.remainingDays}} days:</label>
</div>
+ <a class="btn btn-primary" href="/name/{{.label}}/buy">Extend registration for {{.extensionDaysCount}} days until <b>{{.extendedExpiration}}</b> for <b>{{.cost}}</b></a>
</div>
- <hr/>
- <a class="btn btn-secondary" href="/">Back</a>
</div>
- {{end}}
- </body>
+ </div>
+ {{end}}
+ <hr/>
+ <a class="btn btn-secondary" href="/">Back</a>
+ </body>
</html>