commit 175dd7e04feac6ce0ceba4a2f37b076df336de43
parent d7459187752f7adecd4202087d2edad38951d775
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Mon, 11 Dec 2023 20:15:41 +0100
edit value and extend registration
Diffstat:
2 files changed, 153 insertions(+), 25 deletions(-)
diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go
@@ -272,7 +272,7 @@ func (t *Registrar) setupRegistrationMetadataBeforePayment(label string, zkey st
OrderID: orderId,
NeedsPaymentUntil: paymentUntil,
RegistrationID: regId,
- Expiration: uint64(time.Now().Add(t.RelativeRegistrationExpiration).UnixMicro()),
+ Expiration: 0,
}
metadataRecordValue, err := json.Marshal(registrationMetadata)
if nil != err {
@@ -284,6 +284,79 @@ func (t *Registrar) setupRegistrationMetadataBeforePayment(label string, zkey st
return t.createOrUpdateRegistration(&namestoreRequest)
}
+func (t *Registrar) updateRegistration(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ var namestoreResponse NamestoreRecord
+ var zkeyRecord RecordData
+ var metaRecord RecordData
+ var regMetadata *RegistrationMetadata
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ client := &http.Client{}
+ req, _ := http.NewRequest(http.MethodGet,t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + vars["label"] + "?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(vars["label"], &namestoreResponse)
+ if err != nil {
+ http.Redirect(w, r, "/" + "?error=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/" + vars["label"] + "?error=Error determining zone status", http.StatusSeeOther)
+ return
+ }
+ if nil == regMetadata {
+ http.Redirect(w, r, "/name/"+vars["label"], http.StatusSeeOther)
+ return
+ }
+ r.ParseForm()
+ token := r.Form.Get("token")
+ zkey := r.Form.Get("zkey")
+ if regMetadata.RegistrationID != token {
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Unauthorized", http.StatusSeeOther)
+ return
+ }
+ for _, record := range namestoreResponse.Records {
+ if isDelegationRecordType(record.RecordType) {
+ zkeyRecord = record
+ } else {
+ metaRecord = record
+ }
+ }
+ zkeyRecord.Value = zkey
+ zkeyRecord.RecordType = guessDelegationRecordType(zkey)
+ namestoreResponse.Records = []RecordData{metaRecord, zkeyRecord}
+ err = t.createOrUpdateRegistration(&namestoreResponse)
+ if nil != err {
+ fmt.Println(err)
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Update: Internal error", http.StatusSeeOther)
+ return
+ }
+ http.Redirect(w, r, "/name/"+vars["label"] + "/edit?token=" + token, http.StatusSeeOther)
+ return
+}
+
func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
var namestoreResponse NamestoreRecord
@@ -297,6 +370,7 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) {
}
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
}
@@ -304,19 +378,19 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) {
if http.StatusOK == resp.StatusCode {
respData, err := io.ReadAll(resp.Body)
if err != nil {
- http.Redirect(w, r, "/name/" + vars["label"] + "?error=Error determining zone status", http.StatusSeeOther)
+ 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, "/name/" + vars["label"] + "?error=Error determining zone status", http.StatusSeeOther)
+ 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(vars["label"], &namestoreResponse)
if err != nil {
- http.Redirect(w, r, "/name/" + vars["label"] + "?error=Failed to get registration metadata", http.StatusSeeOther)
+ http.Redirect(w, r, "/" + "?error=Failed to get registration metadata", http.StatusSeeOther)
fmt.Printf("Failed to get registration metadata" + err.Error())
return
}
@@ -365,6 +439,7 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
}
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
}
@@ -372,16 +447,19 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
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(vars["label"], &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
}
@@ -390,12 +468,18 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
return
}
var errorMsg = ""
+ var regId = ""
if nil != regMetadata {
- http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Pending buy order", http.StatusSeeOther)
- return
+ if regMetadata.Paid == false {
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Pending buy order", http.StatusSeeOther)
+ return
+ }
+ regMetadata.Paid = false
+ regId = regMetadata.RegistrationID
+ } else {
+ regId = generateRegistrationId()
}
summaryMsg := strings.Replace(t.SummaryTemplateString, "${NAME}", vars["label"], 1)
- regId := generateRegistrationId()
orderID, newOrderErr := t.Merchant.AddNewOrder(*t.RegistrationCost, summaryMsg, t.BaseUrl + "/name/" + vars["label"] + "/edit?token=" + regId)
if newOrderErr != nil {
fmt.Println(newOrderErr)
@@ -413,17 +497,46 @@ func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
return
}
paymentUntil := time.Now().Add(t.PaymentExpiration)
- err = t.setupRegistrationMetadataBeforePayment(vars["label"], r.URL.Query().Get("zkey"), orderID, paymentUntil, regId)
- if err != nil {
- fmt.Println(err)
- http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Internal error", http.StatusSeeOther)
- return
+ if nil != regMetadata {
+ var newZkeyRecord RecordData
+ var metaRecord RecordData
+ for _, record := range namestoreResponse.Records {
+ if isDelegationRecordType(record.RecordType) {
+ record.IsPrivate = false
+ newZkeyRecord = record
+ } else {
+ metaRecord = record
+ }
+ }
+ regMetadata.NeedsPaymentUntil = paymentUntil
+ regMetadata.OrderID = orderID
+ metadataRecordValue, err := json.Marshal(regMetadata)
+ if nil != err {
+ fmt.Println(err)
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Internal error", http.StatusSeeOther)
+ return
+ }
+ metaRecord.Value = string(metadataRecordValue)
+ namestoreResponse.Records = []RecordData{metaRecord, newZkeyRecord}
+ err = t.createOrUpdateRegistration(&namestoreResponse)
+ if nil != err {
+ fmt.Println(err)
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Internal error", http.StatusSeeOther)
+ return
+ }
+ } else {
+ err = t.setupRegistrationMetadataBeforePayment(vars["label"], r.URL.Query().Get("zkey"), orderID, paymentUntil, regId)
+ if err != nil {
+ fmt.Println(err)
+ http.Redirect(w, r, "/name/"+vars["label"] + "?error=Registration failed: Internal error", http.StatusSeeOther)
+ return
+ }
}
encodedPng := base64.StdEncoding.EncodeToString(qrPng)
fullData := map[string]interface{}{
"qrCode": template.URL("data:image/png;base64," + encodedPng),
"payto": template.URL(payto),
- "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + vars["label"]),
+ "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + vars["label"] + "/edit?token=" + regId),
"label": vars["label"],
"error": errorMsg,
"cost": t.localizedAmountString(),
@@ -449,13 +562,18 @@ func (t *Registrar) getCurrentRegistrationMetadata(label string, nsRecord *Names
if !haveMetadata {
return nil, nil
}
+ // Does this registration have an unpaid order? if yes, check payment status and update if necessary.
if !regMetadata.Paid {
rc, payto, paytoErr := t.Merchant.IsOrderPaid(regMetadata.OrderID)
if nil != paytoErr {
if rc == http.StatusNotFound {
- fmt.Printf("Registration for %s not found, removing\n", label)
- t.expireRegistration(label)
- return nil, nil
+ if time.Now().After(time.UnixMicro(int64(regMetadata.Expiration))) {
+ fmt.Printf("Registration for %s not found, removing\n", label)
+ t.expireRegistration(label)
+ return nil, nil
+ } else {
+ return ®Metadata, nil
+ }
}
return nil, errors.New("Error determining payment status: " + paytoErr.Error())
}
@@ -478,10 +596,22 @@ func (t *Registrar) getCurrentRegistrationMetadata(label string, nsRecord *Names
newMetaRecord = record
}
}
+ // Note how for every time the payment is completed, the registration duration increases
+ regMetadata.Expiration += uint64(t.RelativeRegistrationExpiration.Microseconds())
+ metadataRecordValue, err := json.Marshal(regMetadata)
+ if nil != err {
+ return nil, err
+ }
+ newMetaRecord.Value = string(metadataRecordValue)
nsRecord.Records = []RecordData{newMetaRecord, newZkeyRecord}
- t.createOrUpdateRegistration(nsRecord)
+ err = t.createOrUpdateRegistration(nsRecord)
+ if nil != err {
+ return nil, err
+ }
+ return ®Metadata, nil
} else {
- if time.Now().After(regMetadata.NeedsPaymentUntil) {
+ // Remove metadata if payment limit exceeded and registration expired
+ if time.Now().After(regMetadata.NeedsPaymentUntil) && time.Now().After(time.UnixMicro(int64(regMetadata.Expiration))) {
fmt.Printf("Payment request for %s has expired, removing\n", label)
t.expireRegistration(label)
return nil, nil
@@ -584,6 +714,7 @@ func (t *Registrar) setupHandlers() {
t.Router.HandleFunc("/name/{label}", t.namePage).Methods("GET")
t.Router.HandleFunc("/name/{label}/buy", t.buyPage).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")
/* ToS API */
diff --git a/web/templates/edit.html b/web/templates/edit.html
@@ -32,14 +32,11 @@
</div>
</form>
<span>Registration valid until: <i>{{.registeredUntil}}</i></span><br/>
- <form action="/name/{{.label}}/renew" method="post" class="align-items-center pt-5">
- <div class="row">
- <div class="col-lg-12">
- <input class="btn btn-primary" type="submit" value="Extend registration until {{.extendedExpiration}} for {{.cost}}">
- <input type="hidden" value="{{.token}}" name="token">
- </div>
+ <div class="row mt-5">
+ <div class="col-lg-12">
+ <a class="btn btn-primary" href="/name/{{.label}}/buy">Extend registration until {{.extendedExpiration}} for {{.cost}}</a>
</div>
- </form>
+ </div>
<a class="btn btn-primary mt-5" href="/">Back</a>
</div>
</body>