commit c72db71ea48e9023b2f2dbb68d1e144a5c729731
parent 5b0eaec6a47cdc27094d8b03ee75bf07bc5bfdcc
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Tue, 5 Dec 2023 08:20:17 +0100
Use path elements for labels and actions
Diffstat:
3 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go
@@ -32,6 +32,12 @@ import (
"taler.net/taler-go.git/pkg/merchant"
)
+type IdentityInfo struct {
+ Pubkey string `json:"pubkey"`
+ Name string `json:"name"`
+}
+
+
type GnunetError struct {
Description string `json:"error"`
Code uint32 `json:"error_code"`
@@ -83,6 +89,10 @@ type Registrar struct {
// Name of our root zone
RootZoneName string
+
+ // Key of our root zone
+ RootZoneKey string
+
// Suggested suffix for our zone
SuffixHint string
@@ -91,6 +101,12 @@ type Registrar struct {
// Registration policy; fcfs or paid
RegistrationPolicy string
+
+ // Cost for a registration
+ RegistrationCost uint64
+
+ // Currency to use
+ RegistrationCostCurrency string
}
type VersionResponse struct {
@@ -114,12 +130,14 @@ func (t *Registrar) landingPage(w http.ResponseWriter, r *http.Request) {
fullData := map[string]interface{}{
"suffixHint": t.SuffixHint,
+ "zoneKey": t.RootZoneKey,
}
t.LandingTpl.Execute(w, fullData)
return
}
func (t *Registrar) registerName(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
var namestoreRequest NamestoreRecord
var delegationRecord RecordData
var gnunetError GnunetError
@@ -131,7 +149,7 @@ func (t *Registrar) registerName(w http.ResponseWriter, r *http.Request) {
delegationRecord.RecordType = "PKEY" // FIXME
delegationRecord.RelativeExpiration = t.RelativeDelegationExpiration
delegationRecord.Value = r.URL.Query().Get("zkey")
- namestoreRequest.RecordName = r.URL.Query().Get("label")
+ namestoreRequest.RecordName = vars["label"]
namestoreRequest.Records = []RecordData{delegationRecord}
reqString, _ := json.Marshal(namestoreRequest)
// FIXME handle errors here
@@ -146,20 +164,35 @@ func (t *Registrar) registerName(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/name?label="+r.URL.Query().Get("label") + "&error=" + gnunetError.Description, http.StatusSeeOther)
return
}
- http.Redirect(w, r, "/name?label="+r.URL.Query().Get("label") + "®istered=true", http.StatusSeeOther)
+ http.Redirect(w, r, "/name/"+ vars["label"] + "?registered=true", http.StatusSeeOther)
return
}
+func (t *Registrar) searchPage(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ http.Redirect(w, r, "/name/"+r.URL.Query().Get("label"), http.StatusSeeOther)
+ return
+}
+
+func (t *Registrar) buyPage(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ if t.RegistrationCost == 0 {
+ http.Redirect(w, r, "/name/"+vars["label"]+"/register?zkey="+r.URL.Query().Get("zkey"), http.StatusSeeOther)
+ }
+ http.Redirect(w, r, "/name/"+vars["label"]+"?error=Not implemented", http.StatusSeeOther)
+ return
+}
func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) {
var namestoreResponse NamestoreRecord
+ vars := mux.Vars(r)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
var available = false
var value = ""
var registered = r.URL.Query().Get("registered") == "true"
// FIXME redirect back if label empty
- resp, err := http.Get(t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + r.URL.Query().Get("label"))
+ resp, err := http.Get(t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + vars["label"])
if err != nil {
fmt.Printf("Failed to get zone contents")
return
@@ -184,7 +217,10 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) {
return
}
fullData := map[string]interface{}{
- "label": r.URL.Query().Get("label"),
+ "label": vars["label"],
+ "error": r.URL.Query().Get("error"),
+ "cost": t.RegistrationCost,
+ "currency": t.RegistrationCostCurrency,
"available": available,
"currentValue": value,
"suffixHint": t.SuffixHint,
@@ -227,8 +263,10 @@ func (t *Registrar) setupHandlers() {
t.Router = mux.NewRouter().StrictSlash(true)
t.Router.HandleFunc("/", t.landingPage).Methods("GET")
- t.Router.HandleFunc("/name", t.namePage).Methods("GET")
- t.Router.HandleFunc("/register", t.registerName).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}/register", t.registerName).Methods("GET")
+ t.Router.HandleFunc("/search", t.searchPage).Methods("GET")
t.Router.HandleFunc("/names", t.allNamesPage).Methods("GET")
/* ToS API */
@@ -244,6 +282,7 @@ func (t *Registrar) setupHandlers() {
// Initialize the gnsregistrar instance with cfgfile
func (t *Registrar) Initialize(cfgfile string) {
+ var identityResponse IdentityInfo
_cfg, err := ini.Load(cfgfile)
if err != nil {
fmt.Printf("Failed to read config: %v", err)
@@ -268,11 +307,37 @@ func (t *Registrar) Initialize(cfgfile string) {
if err != nil {
fmt.Println(err)
}
+ t.RegistrationCost = t.Cfg.Section("gns-registrar").Key("registration_cost").MustUint64(0)
t.RelativeDelegationExpiration = t.Cfg.Section("gns-registrar").Key("relative_delegation_expiration").MustUint64(86400000)
- t.RegistrationPolicy = t.Cfg.Section("gns-registrar").Key("registration_policy").MustString("paid")
+ t.RegistrationCostCurrency = t.Cfg.Section("gns-registrar").Key("registration_cost_currency").MustString("EUR")
t.SuffixHint = t.Cfg.Section("gns-registrar").Key("suffix_hint").MustString("example.alt")
t.RootZoneName = t.Cfg.Section("gns-registrar").Key("root_zone_name").MustString("master")
t.GnunetUrl = t.Cfg.Section("gns-registrar").Key("gnunet_baseurl_private").MustString("http://localhost:7776")
+ resp, err := http.Get(t.GnunetUrl + "/identity/name/" + t.RootZoneName)
+ if err != nil {
+ fmt.Printf("Failed to get zone key")
+ return
+ }
+ defer resp.Body.Close()
+ if http.StatusNotFound == resp.StatusCode {
+ fmt.Printf("Zone not found.")
+ os.Exit(1)
+ } else if http.StatusOK == resp.StatusCode {
+ respData, err := io.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Printf("Failed to get zone contents" + err.Error())
+ os.Exit(1)
+ }
+ err = json.NewDecoder(bytes.NewReader(respData)).Decode(&identityResponse)
+ if err != nil {
+ fmt.Printf("Failed to get zone contents" + err.Error())
+ os.Exit(1)
+ }
+ t.RootZoneKey = identityResponse.Pubkey
+ } else {
+ fmt.Printf("Failed to get zone contents" + err.Error())
+ os.Exit(1)
+ }
merchURL := t.Cfg.Section("gns-registrar").Key("merchant_baseurl_private").MustString("http://merchant.gnsregistrar/instances/myInstance")
merchToken := t.Cfg.Section("gns-registrar").Key("merchant_token").MustString("secretAccessToken")
t.Merchant = merchant.NewMerchant(merchURL, merchToken)
diff --git a/web/templates/landing.html b/web/templates/landing.html
@@ -9,8 +9,8 @@
</head>
<body>
<div class="container pt-5">
- <h1 class="text-center mb-5">.{{.suffixHint}} is TODOFIXMETHEACTUALKEY</h1>
- <form action="/name" method="get">
+ <h1 class="text-center mb-5">.{{.suffixHint}} is {{.zoneKey}}</h1>
+ <form action="/search" method="get">
<label for="label" class="form-label">Check availability:</label>
<div class="input-group mb-2 w-50">
<input id="label" name="label" class="form-control form-control-lg text-end" maxlength="63" type="text" aria-describedby="reg-suffix" required autofocus>
@@ -24,7 +24,7 @@
<h4 class="alert-heading">The .{{.suffixHint}} Zone!</h4>
<p>If you do not have our zone configured in your <i>Start Zones</i>, we suggest to do it as:</p>
<hr>
- <p class="mb-0">.{{.suffixHint}} = TODOFIXMETHEACTUALKEY</p>
+ <p class="mb-0">.{{.suffixHint}} = {{.zoneKey}}</p>
</div>
</div>
</body>
diff --git a/web/templates/name.html b/web/templates/name.html
@@ -17,24 +17,33 @@
</div>
</div>
{{end}}
+ {{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>
+ </div>
+ {{end}}
<div class="container pt-5">
{{if .available}}
<h1 class="mb-5"><i class="text-primary">{{.label}}</i> is still <span class="text-success">available</span> for registration.</h1>
- <form action="/register" method="get" class="align-items-center">
+ <form action="/name/{{.label}}/buy" method="get" class="align-items-center">
<div class="input-group mb-2 w-75">
<span class="input-group-text" id="reg-prefix"><i class="text-primary">{{.label}}</i>.<i class="text-secondary">{{.suffixHint}}</i>: </span>
<input type="hidden" name="label" value="{{.label}}">
<input name="zkey" class="form-control form-control-lg" maxlength="63" type="text" placeholder="Enter your zone key here!" required autofocus>
- {{if eq .registrationPolicy "fcfs"}}
- <input class="btn btn-primary" type="submit" value="Register">
+ {{if eq .cost 0}}
+ <input class="btn btn-primary" type="submit" value="Register for free">
{{else}}
- <input class="btn btn-primary" type="submit" value="Buy">
+ <input class="btn btn-primary" type="submit" value="Register for {{.cost}} {{.currency}}">
{{end}}
</div>
</form>
{{else}}
<h1 class="mb-5"><i class="text-primary">{{.label}}</i> is already <span class="text-danger">taken</span>!</h1>
- <form action="/renew" method="get" class="align-items-center">
+ <form action="/name/{{.label}}/renew" method="get" class="align-items-center">
<div class="input-group mb-2 w-75">
<span class="input-group-text" id="reg-prefix"><i class="text-primary">{{.label}}</i>.<i class="text-secondary">{{.suffixHint}}</i>: </span>
<input name="label" disabled="{{.modificationAllowed}}" class="form-control form-control-lg" maxlength="63" type="text" placeholder="Enter your zone key here!" value="{{.currentValue}}" required autofocus>