gnunet-gns-registrar

GNU Name System registrar
Log | Files | Refs | README

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:
Mgns-registrar.conf | 1+
Mpkg/rest/gnsregistrar.go | 83+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mweb/templates/landing.html | 26+++++++++++++++++---------
Mweb/templates/name.html | 33++++++++++++++++++++-------------
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>