commit 7e3e8ebe886dd8ac6ea9de88d87f236498c688eb
parent 6455197939b0db54055ab1cb649116b514db2cda
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Mon, 4 Dec 2023 21:55:48 +0100
Towards functioning fcfs mode. Allow registrations of PKEY
Diffstat:
4 files changed, 92 insertions(+), 51 deletions(-)
diff --git a/gns-registrar.conf b/gns-registrar.conf
@@ -16,3 +16,4 @@ registrar_name = web/templates/name.html
registration_failed = templates/registration_failed.html
registration_duration = 1y
root_zone_name = test
+registration_policy = fcfs
diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go
@@ -26,13 +26,17 @@ import (
"io"
"net/http"
"os"
- "time"
"github.com/gorilla/mux"
"gopkg.in/ini.v1"
"taler.net/taler-go.git/pkg/merchant"
)
+type GnunetError struct {
+ Description string `json:"error"`
+ Code uint32 `json:"error_code"`
+}
+
type RecordData struct {
Value string `json:"value"`
RecordType string `json:"record_type"`
@@ -40,6 +44,7 @@ type RecordData struct {
IsPrivate bool `json:"is_private"`
IsRelativeExpiration bool `json:"is_relative_expiration"`
IsSupplemental bool `json:"is_supplemental"`
+ IsShadow bool `json:"is_shadow"`
}
@@ -69,35 +74,20 @@ type Registrar struct {
// all names page
AllNamesTpl *template.Template
- // The address salt
- Salt string
-
- // The timeframe for the validation requests
- ValidationTimeframe time.Duration
-
- // How often may a challenge be requested
- ValidationInitiationMax int64
-
- // How often may a solution be attempted (in the given timeframe)
- SolutionAttemptsMax int
-
- // The timeframe for the above solution attempts
- SolutionTimeframe time.Duration
-
- // Challenge length in bytes before encoding
- ChallengeBytes int
-
// Merchant object
Merchant merchant.Merchant
- // Monthly fee amount
- MonthlyFee string
+ // Relative record expiration (NOT registration expiration!)
+ RelativeDelegationExpiration uint64
// Name of our root zone
RootZoneName string
// Gnunet REST API basename
GnunetUrl string
+
+ // Registration policy; fcfs or paid
+ RegistrationPolicy string
}
type VersionResponse struct {
@@ -126,6 +116,37 @@ func (t *Registrar) landingPage(w http.ResponseWriter, r *http.Request) {
return
}
+func (t *Registrar) registerName(w http.ResponseWriter, r *http.Request) {
+ var namestoreRequest NamestoreRecord
+ var delegationRecord RecordData
+ var gnunetError GnunetError
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ delegationRecord.IsPrivate = false
+ delegationRecord.IsRelativeExpiration = true
+ delegationRecord.IsSupplemental = false
+ delegationRecord.IsShadow = false
+ delegationRecord.RecordType = "PKEY" // FIXME
+ delegationRecord.RelativeExpiration = t.RelativeDelegationExpiration
+ delegationRecord.Value = r.URL.Query().Get("zkey")
+ namestoreRequest.RecordName = r.URL.Query().Get("label")
+ namestoreRequest.Records = []RecordData{delegationRecord}
+ reqString, _ := json.Marshal(namestoreRequest)
+ // FIXME handle errors here
+ fmt.Println(namestoreRequest)
+ resp, err := http.Post(t.GnunetUrl+"/namestore/" + t.RootZoneName, "application/json", bytes.NewBuffer(reqString))
+ resp.Body.Close()
+ if http.StatusNoContent != resp.StatusCode {
+ fmt.Printf("Got error: %d\n", resp.StatusCode)
+ json.NewDecoder(resp.Body).Decode(&gnunetError)
+ fmt.Println(gnunetError.Code)
+ fmt.Println(err)
+ }
+ http.Redirect(w, r, "/name?label="+r.URL.Query().Get("label"), http.StatusSeeOther)
+ return
+}
+
+
+
func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) {
var namestoreResponse NamestoreRecord
w.Header().Set("Content-Type", "text/html; charset=utf-8")
@@ -133,12 +154,12 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) {
var value = ""
// FIXME redirect back if label empty
resp, err := http.Get(t.GnunetUrl + "/namestore/" + t.RootZoneName + "/" + r.URL.Query().Get("label"))
- if err != nil {
+ if err != nil {
fmt.Printf("Failed to get zone contents")
return
}
defer resp.Body.Close()
- if http.StatusNotFound == resp.StatusCode {
+ if http.StatusNotFound == resp.StatusCode {
available = true
} else if http.StatusOK == resp.StatusCode {
respData, err := io.ReadAll(resp.Body)
@@ -161,6 +182,7 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) {
"available": available,
"currentValue": value,
"registrarSuffix": t.RootZoneName,
+ "registrationPolicy": t.RegistrationPolicy,
}
t.NameTpl.Execute(w, fullData)
return
@@ -170,22 +192,22 @@ func (t *Registrar) allNamesPage(w http.ResponseWriter, r *http.Request) {
var namestoreResponse []NamestoreRecord
w.Header().Set("Content-Type", "text/html; charset=utf-8")
resp, err := http.Get(t.GnunetUrl + "/namestore/" + t.RootZoneName)
- if err != nil {
+ if err != nil {
fmt.Printf("Failed to get zone contents")
return
}
defer resp.Body.Close()
- if http.StatusOK != resp.StatusCode {
+ if http.StatusOK != resp.StatusCode {
fmt.Printf("Failed to get zone contents. Retcode=%d", resp.StatusCode)
return
}
respData, err := io.ReadAll(resp.Body)
- if err != nil {
+ if err != nil {
fmt.Printf("Failed to get zone contents" + err.Error())
return
}
err = json.NewDecoder(bytes.NewReader(respData)).Decode(&namestoreResponse)
- if err != nil {
+ if err != nil {
fmt.Printf("Failed to get zone contents" + err.Error())
return
}
@@ -199,6 +221,7 @@ func (t *Registrar) setupHandlers() {
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("/names", t.allNamesPage).Methods("GET")
/* ToS API */
@@ -238,8 +261,10 @@ func (t *Registrar) Initialize(cfgfile string) {
if err != nil {
fmt.Println(err)
}
- 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")
+ 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.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")
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
@@ -8,15 +8,23 @@
<title>GNS Registrar</title>
</head>
<body>
- <div class="container pt-5">
- <h1>Lookup your domain name.</h1>
- <form action="/name" method="get" class="align-items-center">
- <div class="input-group mb-2">
- <input name="label" class="form-control text-end" maxlength="63" type="text" placeholder="Check if your name is still available!" aria-describedby="reg-suffix" required autofocus>
- <span class="input-group-text" id="reg-suffix">.{{.registrarSuffix}}</span>
- <input class="btn btn-primary" type="submit" value="Search">
- </div>
- </form>
+ <div class="container pt-5">
+ <h1>Lookup your domain name.</h1>
+ <form action="/name" method="get" class="text-center">
+ <div class="input-group mb-2 w-50">
+ <input name="label" class="form-control form-control-lg text-end" maxlength="63" type="text" placeholder="Check if your name is still available!" aria-describedby="reg-suffix" required autofocus>
+ <span class="input-group-text" id="reg-suffix">.{{.registrarSuffix}}</span>
+ <input class="btn btn-primary" type="submit" value="Check!">
+ </div>
+ </form>
+ </div>
+ <div class="container pt-5">
+ <div class="alert alert-light" role="alert">
+ <h4 class="alert-heading">The .{{.registrarSuffix}} 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">.{{.registrarSuffix}} = TODOFIXMETHEACTUALKEY</p>
</div>
+ </div>
</body>
</html>
diff --git a/web/templates/name.html b/web/templates/name.html
@@ -8,29 +8,36 @@
<title>Name Overview</title>
</head>
<body>
- <div class="container pt-5 align-items-center">
+ <div class="container pt-5">
{{if .available}}
- <h1><i class="text-success">{{.label}}</i>.<i class="text-secondary">{{.registrarSuffix}}</i> is available.</h1>
- <form action="/buy" method="get" class="align-items-center">
- <div class="input-group mb-2 w-50">
- <input name="label" class="form-control text-end" maxlength="63" type="text" placeholder="Enter your zone key here!" aria-describedby="reg-suffix" required autofocus>
- <span class="input-group-text" id="reg-suffix">.{{.registrarSuffix}}</span>
+ <h1><i class="text-primary">{{.label}}</i>.<i class="text-secondary">{{.registrarSuffix}}</i> is still <span class="text-success">available<span>.</h1>
+ <form action="/register" method="get" class="align-items-center">
+ <div class="input-group mb-2 w-75">
+ <span class="input-group-text" id="reg-prefix">{{.label}}.{{.registrarSuffix}}: </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">
+ {{else}}
<input class="btn btn-primary" type="submit" value="Buy">
+ {{end}}
</div>
</form>
{{else}}
- <h1><i class="text-primary">{{.label}}</i>.<i class="text-secondary">{{.registrarSuffix}}</i> is already taken!</h1>
+ <h1><i class="text-primary">{{.label}}</i>.<i class="text-secondary">{{.registrarSuffix}}</i> is already <span class="text-danger">taken</span>!</h1>
<form action="/renew" method="get" class="align-items-center">
- <div class="input-group mb-2">
- <input name="label" class="form-control text-end" maxlength="63" type="text" placeholder="Enter your zone key here!" value="{{.currentValue}}" aria-describedby="reg-suffix" required autofocus>
- <span class="input-group-text" id="reg-suffix">.{{.registrarSuffix}}</span>
- <input class="btn btn-primary" type="submit" value="Update">
+ <div class="input-group mb-2 w-75">
+ <span class="input-group-text" id="reg-prefix">{{.label}}.{{.registrarSuffix}}: </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>
+ <input class="btn btn-primary" disabled="{{.modificationAllowed}}" type="submit" value="Update">
</div>
</form>
<form action="/renew" method="get" class="align-items-center">
- <span>Valid until: <i>placeholder</i></span><br/>
- <span>Registration extension cose: <i>23 EUR</i></span><br/>
+ <span>Registration valid until: <i>placeholder</i></span><br/>
+ {{if .modificationAllowed}}
+ <span>Registration extension cost: <i>23 EUR</i></span><br/>
<input class="btn btn-primary" type="submit" value="Extend registration">
+ {{end}}
</form>
{{end}}
<a class="btn btn-primary mt-5" href="/">Back</a>