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:
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")