gnunet-gns-registrar

GNU Name System registrar
Log | Files | Refs | README

commit a63db5e5e0189dc7f61b0ecf846012f54d106252
parent b021850c126eab49505b5d44eaffab3d71b16b93
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Tue, 29 Apr 2025 11:23:06 +0200

port config handling from taler components

Diffstat:
Mcmd/gns-registrar/main.go | 57++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mgo.mod | 1+
Mgo.sum | 6++----
Mpkg/rest/gnsregistrar.go | 123++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
4 files changed, 133 insertions(+), 54 deletions(-)

diff --git a/cmd/gns-registrar/main.go b/cmd/gns-registrar/main.go @@ -20,31 +20,78 @@ package main import ( "flag" + "fmt" "log" "net/http" + "os" + "github.com/schanzen/taler-go/pkg/merchant" gnsregistrar "gnunet.org/gnunet-gns-registrar/pkg/rest" + "gopkg.in/ini.v1" + "rsc.io/getopt" ) var ( - t gnsregistrar.Registrar - version string + t gnsregistrar.Registrar + version string + datahome string + verbose bool // FIXME do something with this? ) func handleRequests(r *gnsregistrar.Registrar) { - log.Fatal(http.ListenAndServe(r.Cfg.Section("gns-registrar").Key("bind_to").MustString("localhost:11000"), r.Router)) + log.Fatal(http.ListenAndServe(r.Cfg.Ini.Section("gns-registrar").Key("bind_to").MustString("localhost:11000"), r.Router)) +} + +func printHelp() { + fmt.Print("gnunet-gns-registrar\n\n") + getopt.PrintDefaults() + fmt.Print("\nReport bugs to gnunet-developers@gnu.org.\n", + "Home page: https://taler.net\n", + "General help using GNU software: http://www.gnu.org/gethelp/\n") } func main() { var cfgFlag = flag.String("c", "", "Configuration file to use") + getopt.Alias("c", "config") + // FIXME use flags + loglevelStringOpt := flag.String("L", "INFO", "Log level to use. DEBUG, INFO, WARNING or ERROR") + getopt.Alias("L", "loglevel") + var verboseFlag = flag.Bool("v", false, "Verbose") + getopt.Alias("v", "verbose") + var helpFlag = flag.Bool("h", false, "Print help") + getopt.Alias("h", "help") - flag.Parse() + getopt.Parse() cfgfile := "gns-registrar.conf" log.Println(version) if len(*cfgFlag) != 0 { cfgfile = *cfgFlag } + if *helpFlag { + printHelp() + return + } + verbose = *verboseFlag + loglevel := gnsregistrar.LogInfo + for loglevelNum, loglevelString := range gnsregistrar.LoglevelStringMap { + if loglevelString == *loglevelStringOpt { + loglevel = loglevelNum + } + } + cfg, err := ini.LooseLoad(cfgfile) + if err != nil { + log.Fatalf("Failed to read config: %v", err) + os.Exit(1) + } + merchURL := cfg.Section("gns-registrar").Key("base_url_merchant").MustString("https://backend.demo.taler.net") + merchToken := cfg.Section("gns-registrar").Key("merchant_token").MustString("sandbox") t := gnsregistrar.Registrar{} - t.Initialize(cfgfile, version) + t.Initialize(gnsregistrar.RegistrarConfig{ + Ini: cfg, + Version: version, + Datahome: datahome, + Loglevel: loglevel, + Merchant: merchant.NewMerchant(merchURL, merchToken), + }) handleRequests(&t) } diff --git a/go.mod b/go.mod @@ -8,6 +8,7 @@ require ( github.com/schanzen/taler-go v1.0.8 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e gopkg.in/ini.v1 v1.67.0 + rsc.io/getopt v0.0.0-20170811000552-20be20937449 ) require ( diff --git a/go.sum b/go.sum @@ -1,15 +1,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/schanzen/taler-go v1.0.6 h1:qf34AXE6aFBQkcJ3/V25apWcHLPv81JJgBVlSEUZaW0= -github.com/schanzen/taler-go v1.0.6/go.mod h1:+l2TVAPZkF2d15X/XPLYZI5R6PdW6gc6Wft12jrl7tA= github.com/schanzen/taler-go v1.0.8 h1:vrFtYpE2hgfMrft/hzv3O1NjtjDOF0I44ossRw7pLT0= github.com/schanzen/taler-go v1.0.8/go.mod h1:+l2TVAPZkF2d15X/XPLYZI5R6PdW6gc6Wft12jrl7tA= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= @@ -20,3 +16,5 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/getopt v0.0.0-20170811000552-20be20937449 h1:UukjJOsjQH0DIuyyrcod6CXHS6cdaMMuJmrt+SN1j4A= +rsc.io/getopt v0.0.0-20170811000552-20be20937449/go.mod h1:dhCdeqAxkyt5u3/sKRkUXuHaMXUu1Pt13GTQAM2xnig= diff --git a/pkg/rest/gnsregistrar.go b/pkg/rest/gnsregistrar.go @@ -26,6 +26,7 @@ import ( "fmt" "html/template" "io" + "log" "net/http" "net/url" "os" @@ -42,6 +43,23 @@ import ( "gopkg.in/ini.v1" ) +type RegistrarConfig struct { + // The config to use + Ini *ini.File + + // The Service Version + Version string + + // The data home location (usually $datadir/gnunet-gns-registrar) + Datahome string + + // The merchant connection to use + Merchant merchant.Merchant + + // The loglevel to use + Loglevel LogLevel +} + // This is metadata stored in the namestore next to a registered zone key. // It is always stored in a private metadata record and holds registration information such // as payment status and expiration. @@ -123,10 +141,10 @@ type Registrar struct { Router *mux.Router // Our configuration from the config.json - Cfg *ini.File + Cfg RegistrarConfig - // Version - Version string + // Logger + Logger *log.Logger // Map of supported validators as defined in the configuration Validators map[string]bool @@ -229,7 +247,7 @@ func (t *Registrar) landingPage(w http.ResponseWriter, r *http.Request) { "suffixHint": t.SuffixHint, "extZkey": r.URL.Query().Get("zkey"), "zoneKey": t.RootZoneKey, - "version": t.Version, + "version": t.Cfg.Version, "error": r.URL.Query().Get("error"), } err := t.LandingTpl.Execute(w, fullData) @@ -543,7 +561,7 @@ func (t *Registrar) editRegistration(w http.ResponseWriter, r *http.Request) { "remainingDays": remainingDays, "registeredUntil": registeredUntilStr, "token": r.URL.Query().Get("token"), - "version": t.Version, + "version": t.Cfg.Version, "error": r.URL.Query().Get("error"), "cost": cost, "suffixHint": t.SuffixHint, @@ -637,7 +655,7 @@ func (t *Registrar) paymentPage(w http.ResponseWriter, r *http.Request) { "fulfillmentUrl": template.URL(t.BaseUrl + "/name/" + sanitizedLabel + "/edit?token=" + regMetadata.RegistrationID), "registrationId": regMetadata.RegistrationID, "label": sanitizedLabel, - "version": t.Version, + "version": t.Cfg.Version, "error": errorMsg, "cost": cost, "suffixHint": t.SuffixHint, @@ -936,7 +954,7 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) { cost, _ := t.RegistrationCost.FormatWithCurrencySpecification(t.CurrencySpec) fullData := map[string]interface{}{ "label": sanitizedLabel, - "version": t.Version, + "version": t.Cfg.Version, "error": r.URL.Query().Get("error"), "zkey": r.URL.Query().Get("zkey"), "cost": cost, @@ -954,6 +972,30 @@ func (t *Registrar) namePage(w http.ResponseWriter, r *http.Request) { } } +type LogLevel int + +const ( + LogError LogLevel = iota + LogWarning + LogInfo + LogDebug +) + +var LoglevelStringMap = map[LogLevel]string{ + LogDebug: "DEBUG", + LogError: "ERROR", + LogWarning: "WARN", + LogInfo: "INFO", +} + +func (t *Registrar) Logf(loglevel LogLevel, fmt string, args ...any) { + if loglevel < t.Cfg.Loglevel { + return + } + t.Logger.SetPrefix("taler-directory - " + LoglevelStringMap[loglevel] + " ") + t.Logger.Printf(fmt, args...) +} + func (t *Registrar) setupHandlers() { t.Router = mux.NewRouter().StrictSlash(true) @@ -978,71 +1020,64 @@ func (t *Registrar) setupHandlers() { } // Initialize the gnsregistrar instance with cfgfile -func (t *Registrar) Initialize(cfgfile string, version string) { - var identityResponse IdentityInfo - _cfg, err := ini.LooseLoad(cfgfile) - if err != nil { - fmt.Printf("Failed to read config: %v", err) - os.Exit(1) - } - _, err = _cfg.WriteTo(os.Stdout) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - t.Cfg = _cfg - if t.Cfg.Section("gns-registrar").Key("production").MustBool(false) { +func (t *Registrar) Initialize(cfg RegistrarConfig) { + var ( + identityResponse IdentityInfo + err error + ) + t.Cfg = cfg + t.Logger = log.New(os.Stdout, "gnunet-gns-registrar:", log.LstdFlags) + if t.Cfg.Ini.Section("gns-registrar").Key("production").MustBool(false) { fmt.Println("Production mode enabled") } - t.Version = version - navTplFile := t.Cfg.Section("gns-registrar").Key("nav_template").MustString("web/templates/nav.html") - footerTplFile := t.Cfg.Section("gns-registrar").Key("footer_template").MustString("web/templates/footer.html") - landingTplFile := t.Cfg.Section("gns-registrar").Key("landing_template").MustString("web/templates/landing.html") + navTplFile := t.Cfg.Ini.Section("gns-registrar").Key("nav_template").MustString("web/templates/nav.html") + footerTplFile := t.Cfg.Ini.Section("gns-registrar").Key("footer_template").MustString("web/templates/footer.html") + landingTplFile := t.Cfg.Ini.Section("gns-registrar").Key("landing_template").MustString("web/templates/landing.html") t.LandingTpl, err = template.ParseFiles(landingTplFile, navTplFile, footerTplFile) if err != nil { fmt.Println(err) os.Exit(1) } - nameTplFile := t.Cfg.Section("gns-registrar").Key("name_template").MustString("web/templates/name.html") + nameTplFile := t.Cfg.Ini.Section("gns-registrar").Key("name_template").MustString("web/templates/name.html") t.NameTpl, err = template.ParseFiles(nameTplFile, navTplFile, footerTplFile) if err != nil { fmt.Println(err) os.Exit(1) } - buyTplFile := t.Cfg.Section("gns-registrar").Key("buy_template").MustString("web/templates/buy.html") + buyTplFile := t.Cfg.Ini.Section("gns-registrar").Key("buy_template").MustString("web/templates/buy.html") t.BuyTpl, err = template.ParseFiles(buyTplFile, navTplFile, footerTplFile) if err != nil { fmt.Println(err) os.Exit(1) } - editTplFile := t.Cfg.Section("gns-registrar").Key("edit_template").MustString("web/templates/edit.html") + editTplFile := t.Cfg.Ini.Section("gns-registrar").Key("edit_template").MustString("web/templates/edit.html") t.EditTpl, err = template.ParseFiles(editTplFile, navTplFile, footerTplFile) if err != nil { fmt.Println(err) os.Exit(1) } - paymentExp := t.Cfg.Section("gns-registrar").Key("payment_required_expiration").MustString("1h") - recordExp := t.Cfg.Section("gns-registrar").Key("relative_delegation_expiration").MustString("24h") - t.RegistrationExpirationDaysCount = t.Cfg.Section("gns-registrar").Key("registration_duration_days").MustUint64(5) + paymentExp := t.Cfg.Ini.Section("gns-registrar").Key("payment_required_expiration").MustString("1h") + recordExp := t.Cfg.Ini.Section("gns-registrar").Key("relative_delegation_expiration").MustString("24h") + t.RegistrationExpirationDaysCount = t.Cfg.Ini.Section("gns-registrar").Key("registration_duration_days").MustUint64(5) t.RelativeRegistrationExpiration, _ = time.ParseDuration(fmt.Sprintf("%dh", t.RegistrationExpirationDaysCount*24)) t.RelativeDelegationExpiration, _ = time.ParseDuration(recordExp) t.PaymentExpiration, _ = time.ParseDuration(paymentExp) - costStr := t.Cfg.Section("gns-registrar").Key("registration_cost").MustString("KUDOS:0.3") + costStr := t.Cfg.Ini.Section("gns-registrar").Key("registration_cost").MustString("KUDOS:0.3") t.RegistrationCost, err = talerutil.ParseAmount(costStr) if err != nil { fmt.Printf("Error parsing amount %s: %s\n", costStr, err.Error()) os.Exit(1) } - t.BaseUrl = t.Cfg.Section("gns-registrar").Key("base_url").MustString("http://localhost:11000") - t.SuffixHint = t.Cfg.Section("gns-registrar").Key("suffix_hint").MustString("example.alt") - t.SummaryTemplateString = t.Cfg.Section("gns-registrar").Key("order_summary_template").MustString("Registration of `${NAME}' at GNUnet FCFS registrar") - t.RootZoneName = t.Cfg.Section("gns-registrar").Key("root_zone_name").MustString("test") - t.GnunetUrl = t.Cfg.Section("gns-registrar").Key("base_url_gnunet").MustString("http://localhost:7776") - t.GnunetBasicAuthEnabled = t.Cfg.Section("gns-registrar").Key("basic_auth_gnunet_enabled").MustBool(true) - t.GnunetUsername = t.Cfg.Section("gns-registrar").Key("basic_auth_gnunet_username").MustString("jdoe") - t.GnunetPassword = t.Cfg.Section("gns-registrar").Key("basic_auth_gnunet_password").MustString("secret") - t.ValidLabelRegex = t.Cfg.Section("gns-registrar").Key("valid_label_regex").MustString("") - t.ValidLabelScript = t.Cfg.Section("gns-registrar").Key("valid_label_script").MustString("") + t.BaseUrl = t.Cfg.Ini.Section("gns-registrar").Key("base_url").MustString("http://localhost:11000") + t.SuffixHint = t.Cfg.Ini.Section("gns-registrar").Key("suffix_hint").MustString("example.alt") + t.SummaryTemplateString = t.Cfg.Ini.Section("gns-registrar").Key("order_summary_template").MustString("Registration of `${NAME}' at GNUnet FCFS registrar") + t.RootZoneName = t.Cfg.Ini.Section("gns-registrar").Key("root_zone_name").MustString("test") + t.GnunetUrl = t.Cfg.Ini.Section("gns-registrar").Key("base_url_gnunet").MustString("http://localhost:7776") + t.GnunetBasicAuthEnabled = t.Cfg.Ini.Section("gns-registrar").Key("basic_auth_gnunet_enabled").MustBool(true) + t.GnunetUsername = t.Cfg.Ini.Section("gns-registrar").Key("basic_auth_gnunet_username").MustString("jdoe") + t.GnunetPassword = t.Cfg.Ini.Section("gns-registrar").Key("basic_auth_gnunet_password").MustString("secret") + t.ValidLabelRegex = t.Cfg.Ini.Section("gns-registrar").Key("valid_label_regex").MustString("") + t.ValidLabelScript = t.Cfg.Ini.Section("gns-registrar").Key("valid_label_script").MustString("") client := &http.Client{} req, _ := http.NewRequest(http.MethodGet, t.GnunetUrl+"/identity/name/"+t.RootZoneName, nil) if t.GnunetBasicAuthEnabled { @@ -1074,9 +1109,7 @@ func (t *Registrar) Initialize(cfgfile string, version string) { fmt.Printf("Failed to get zone contents") os.Exit(1) } - merchURL := t.Cfg.Section("gns-registrar").Key("base_url_merchant").MustString("https://backend.demo.taler.net") - merchToken := t.Cfg.Section("gns-registrar").Key("merchant_token").MustString("sandbox") - t.Merchant = merchant.NewMerchant(merchURL, merchToken) + t.Merchant = cfg.Merchant merchConfig, err := t.Merchant.GetConfig() if nil != err { fmt.Printf("Failed to get merchant config")