[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taldir] 01/02: more error handling
From: |
gnunet |
Subject: |
[taldir] 01/02: more error handling |
Date: |
Thu, 23 Jan 2025 13:56:48 +0100 |
This is an automated email from the git hooks/post-receive script.
martin-schanzenbach pushed a commit to branch master
in repository taldir.
commit cd47ac4772a7739a21da47890775e5e469fad360
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Thu Jan 23 13:56:18 2025 +0100
more error handling
---
locales/de-DE/taldir.yml | 1 +
locales/en-US/taldir.yml | 1 +
pkg/rest/taldir.go | 526 ++++++++++++++++++++-------------------
web/templates/landing_email.html | 4 +-
4 files changed, 271 insertions(+), 261 deletions(-)
diff --git a/locales/de-DE/taldir.yml b/locales/de-DE/taldir.yml
index 6f83e19..e727541 100644
--- a/locales/de-DE/taldir.yml
+++ b/locales/de-DE/taldir.yml
@@ -10,6 +10,7 @@ notYetLinked: "`%s` ist noch nicht mit einer
Bezahlsystemadresse verlinkt. Du ka
isLinked: "`%s` ist bereits mit einer Bezahlsystemadresse verlinkt"
paymentSystemAddress: "Bezahlsystemadresse"
linkIt: "Verlinken"
+aliasInvalid: "Alias '%s´ ist ungültig."
lookup: "Suchen"
lookupEmail: "E-Mail-Adresse nachschlagen"
lookupEmailDescription: "Gib eine E-Mail-Adresse (z.B. `jdoe@example.com`) ein
um die dazugehörige Bezahlsystemadresse nachzuschlagen. Wenn diese noch nicht
verlinkt ist, und das Alias unter Dir gehört, hast du dann die Chance dieses
mit einer Bazahlsystemadresse zu verlinken."
diff --git a/locales/en-US/taldir.yml b/locales/en-US/taldir.yml
index 7571397..b500d74 100644
--- a/locales/en-US/taldir.yml
+++ b/locales/en-US/taldir.yml
@@ -10,6 +10,7 @@ notYetLinked: "`%s` is not yet linked with any Payment System
Address. You may u
isLinked: "`%s` is linked with a Payment System Address"
paymentSystemAddress: "Payment System Address"
linkIt: "Link it"
+aliasInvalid: "Alias '%s´ is invalid."
lookup: "Lookup"
lookupEmail: "Lookup Email address"
lookupEmailDescription: "Enter an email address (e.g. `jdoe@example.com`) to
look up the associated Payment System Address. If it is still unlinked and
under your control you will be given the option to link it with a Payment
System Address after lookup."
diff --git a/pkg/rest/taldir.go b/pkg/rest/taldir.go
index 52176fa..8c32b75 100644
--- a/pkg/rest/taldir.go
+++ b/pkg/rest/taldir.go
@@ -671,302 +671,310 @@ func (t *Taldir) validationPage(w http.ResponseWriter,
r *http.Request) {
"version": t.Version,
"QRCode": template.URL("data:image/png;base64," +
encodedPng),
"WalletLink": template.URL(walletLink),
- }
- t.ValidationTpl.Execute(w, fullData)
- } else {
- expectedSolution := util.GenerateSolution(validation.TargetUri,
validation.Challenge)
- fullData := map[string]interface{}{
- "version": t.Version,
- "error": r.URL.Query().Get("error"),
- "target_uri": template.URL(validation.TargetUri),
- "address": template.URL(address),
- "haddress": template.URL(validation.HAddress),
- "solution": template.URL(expectedSolution),
- "tr": t.I18n.GetLocale(r).GetMessage,
- }
- t.ValidationTpl.Execute(w, fullData)
- }
- return
+ "productDisclaimer":
template.HTML(t.I18n.GetLocale(r).GetMessage("productDisclaimer")),
+ }
+ t.ValidationTpl.Execute(w, fullData)
+ } else {
+ expectedSolution := util.GenerateSolution(validation.TargetUri,
validation.Challenge)
+ fullData := map[string]interface{}{
+ "version": t.Version,
+ "error": r.URL.Query().Get("error"),
+ "target_uri": template.URL(validation.TargetUri),
+ "address": template.URL(address),
+ "haddress": template.URL(validation.HAddress),
+ "solution": template.URL(expectedSolution),
+ "productDisclaimer":
template.HTML(t.I18n.GetLocale(r).GetMessage("productDisclaimer")),
+ "tr": t.I18n.GetLocale(r).GetMessage,
+ }
+ t.ValidationTpl.Execute(w, fullData)
+ }
+ return
}
// ClearDatabase nukes the database (for tests)
func (t *Taldir) ClearDatabase() {
- t.Db.Where("1 = 1").Delete(&entry{})
- t.Db.Where("1 = 1").Delete(&validation{})
+ t.Db.Where("1 = 1").Delete(&entry{})
+ t.Db.Where("1 = 1").Delete(&validation{})
}
func (t *Taldir) termsResponse(w http.ResponseWriter, r *http.Request) {
- tos.ServiceTermsResponse(t.Cfg.Section("taldir"), w, r)
+ tos.ServiceTermsResponse(t.Cfg.Section("taldir"), w, r)
}
func (t *Taldir) privacyResponse(w http.ResponseWriter, r *http.Request) {
- tos.PrivacyPolicyResponse(t.Cfg.Section("taldir"), w, r)
+ tos.PrivacyPolicyResponse(t.Cfg.Section("taldir"), w, r)
}
func (t *Taldir) landingPage(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- translateFunc := t.I18n.GetLocale(r).GetMessage
- fullData := map[string]interface{}{
- "validators": t.Validators,
- "version": t.Version,
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ translateFunc := t.I18n.GetLocale(r).GetMessage
+ fullData := map[string]interface{}{
+ "validators": t.Validators,
+ "version": t.Version,
"lookupOrRegisterCardTitle":
template.HTML(translateFunc("lookupOrRegister")),
"selectAliasToLookupOrLinkCardText":
template.HTML(translateFunc("selectAliasToLookupOrLink")),
"productDisclaimer": template.HTML(translateFunc("productDisclaimer")),
- "error": r.URL.Query().Get("error"),
- "tr": translateFunc,
- }
- err := t.LandingPageTpl.Execute(w, fullData)
- if err != nil {
- fmt.Println(err)
- }
- return
+ "error": translateFunc(r.URL.Query().Get("error")),
+ "tr": translateFunc,
+ }
+ err := t.LandingPageTpl.Execute(w, fullData)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return
}
func (t *Taldir) methodLookupResultPage(w http.ResponseWriter, r
*http.Request) {
- var entry entry
- vars := mux.Vars(r)
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
-
- // Check if this validation method is supported or not.
- val, ok := t.Validators[vars["method"]]
- if !ok {
- w.WriteHeader(404)
- return
- }
-
- // Check if alias is valid
- alias := r.URL.Query().Get("address")
- err := val.isAliasValid(alias)
- if nil != err {
- http.Redirect(w, r, fmt.Sprintf("/?error=%s", err),
http.StatusSeeOther)
- return
- }
- hAddressBin := sha512.Sum512([]byte(r.URL.Query().Get("address")))
- hAddress := gnunetutil.EncodeBinaryToString(hAddressBin[:])
- hsAddress := saltHAddress(hAddress, t.Salt)
- found := false
- err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
- if err != nil {
- log.Printf("`%s` not found.\n", hAddress)
- } else {
- found = true
- }
- fullData := map[string]interface{}{
- "version": t.Version,
- "available": !found,
- "method": val.Name,
- "address": r.URL.Query().Get("address"),
- "result": entry.TargetUri,
- "error": r.URL.Query().Get("error"),
- "tr": t.I18n.GetLocale(r).GetMessage,
- }
- err = t.LookupResultPageTpl.Execute(w, fullData)
- if err != nil {
- fmt.Println(err)
- }
- return
+ var entry entry
+ vars := mux.Vars(r)
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+
+ // Check if this validation method is supported or not.
+ val, ok := t.Validators[vars["method"]]
+ if !ok {
+ w.WriteHeader(404)
+ return
+ }
+
+ // Check if alias is valid
+ alias := r.URL.Query().Get("address")
+ err := val.isAliasValid(alias)
+ emsg := ""
+ found := false
+ if nil != err {
+ log.Printf("Not a valid alias\n")
+ emsg = t.I18n.GetLocale(r).GetMessage("aliasInvalid", alias)
+ http.Redirect(w, r, fmt.Sprintf("/landing/" + val.Name + "?error=%s",
emsg), http.StatusSeeOther)
+ return
+ } else {
+ hAddressBin := sha512.Sum512([]byte(r.URL.Query().Get("address")))
+ hAddress := gnunetutil.EncodeBinaryToString(hAddressBin[:])
+ hsAddress := saltHAddress(hAddress, t.Salt)
+ err = t.Db.First(&entry, "hs_address = ?", hsAddress).Error
+ if err != nil {
+ log.Printf("`%s` not found.\n", hAddress)
+ } else {
+ found = true
+ }
+ }
+ fullData := map[string]interface{}{
+ "version": t.Version,
+ "available": !found,
+ "method": val.Name,
+ "address": r.URL.Query().Get("address"),
+ "result": entry.TargetUri,
+ "error": emsg,
+ "productDisclaimer":
template.HTML(t.I18n.GetLocale(r).GetMessage("productDisclaimer")),
+ "tr": t.I18n.GetLocale(r).GetMessage,
+ }
+ err = t.LookupResultPageTpl.Execute(w, fullData)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return
}
func (t *Taldir) methodLandingPage(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
-
- // Check if this validation method is supported or not.
- val, ok := t.Validators[vars["method"]]
- if !ok {
- w.WriteHeader(404)
- return
- }
- fullData := map[string]interface{}{
- "version": t.Version,
- "error": r.URL.Query().Get("error"),
- "tr": t.I18n.GetLocale(r).GetMessage,
- }
- err := val.LandingPageTpl.Execute(w, fullData)
- if err != nil {
- fmt.Println(err)
- }
- return
+ vars := mux.Vars(r)
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+
+ // Check if this validation method is supported or not.
+ val, ok := t.Validators[vars["method"]]
+ if !ok {
+ w.WriteHeader(404)
+ return
+ }
+ fullData := map[string]interface{}{
+ "version": t.Version,
+ "error": r.URL.Query().Get("error"),
+ "productDisclaimer":
template.HTML(t.I18n.GetLocale(r).GetMessage("productDisclaimer")),
+ "tr": t.I18n.GetLocale(r).GetMessage,
+ }
+ err := val.LandingPageTpl.Execute(w, fullData)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return
}
func (t *Taldir) setupHandlers() {
- t.Router = mux.NewRouter().StrictSlash(true)
+ t.Router = mux.NewRouter().StrictSlash(true)
- /* ToS API */
- t.Router.HandleFunc("/terms", t.termsResponse).Methods("GET")
- t.Router.HandleFunc("/privacy", t.privacyResponse).Methods("GET")
+ /* ToS API */
+ t.Router.HandleFunc("/terms", t.termsResponse).Methods("GET")
+ t.Router.HandleFunc("/privacy", t.privacyResponse).Methods("GET")
- /* Config API */
- t.Router.HandleFunc("/config", t.configResponse).Methods("GET")
+ /* Config API */
+ t.Router.HandleFunc("/config", t.configResponse).Methods("GET")
- /* Assets HTML */
- t.Router.PathPrefix("/css").Handler(http.StripPrefix("/css",
http.FileServer(http.Dir("./static/css"))))
-
t.Router.PathPrefix("/fontawesome").Handler(http.StripPrefix("/fontawesome",
http.FileServer(http.Dir("./static/fontawesome"))))
+ /* Assets HTML */
+ t.Router.PathPrefix("/css").Handler(http.StripPrefix("/css",
http.FileServer(http.Dir("./static/css"))))
+ t.Router.PathPrefix("/fontawesome").Handler(http.StripPrefix("/fontawesome",
http.FileServer(http.Dir("./static/fontawesome"))))
- /* Registration API */
- t.Router.HandleFunc("/", t.landingPage).Methods("GET")
- t.Router.HandleFunc("/{h_address}", t.getSingleEntry).Methods("GET")
- t.Router.HandleFunc("/lookup/{method}",
t.methodLookupResultPage).Methods("GET")
- t.Router.HandleFunc("/landing/{method}",
t.methodLandingPage).Methods("GET")
- t.Router.HandleFunc("/register/{method}",
t.registerRequest).Methods("POST")
- t.Router.HandleFunc("/register/{h_address}/{challenge}",
t.validationPage).Methods("GET")
- t.Router.HandleFunc("/{h_address}", t.validationRequest).Methods("POST")
+ /* Registration API */
+ t.Router.HandleFunc("/", t.landingPage).Methods("GET")
+ t.Router.HandleFunc("/{h_address}", t.getSingleEntry).Methods("GET")
+ t.Router.HandleFunc("/lookup/{method}",
t.methodLookupResultPage).Methods("GET")
+ t.Router.HandleFunc("/landing/{method}", t.methodLandingPage).Methods("GET")
+ t.Router.HandleFunc("/register/{method}", t.registerRequest).Methods("POST")
+ t.Router.HandleFunc("/register/{h_address}/{challenge}",
t.validationPage).Methods("GET")
+ t.Router.HandleFunc("/{h_address}", t.validationRequest).Methods("POST")
}
var pluralizeClient = pluralize.NewClient()
func getFuncs(current *i18n.Locale) template.FuncMap {
- return template.FuncMap{
- "plural": func(word string, count int) string {
- return pluralizeClient.Pluralize(word, count, true)
- },
- }
+ return template.FuncMap{
+ "plural": func(word string, count int) string {
+ return pluralizeClient.Pluralize(word, count, true)
+ },
+ }
}
// Initialize the Taldir instance with cfgfile
func (t *Taldir) Initialize(cfgfile string, version string) {
- _cfg, err := ini.LooseLoad(cfgfile)
- if err != nil {
- log.Fatalf("Failed to read config: %v", err)
- os.Exit(1)
- }
- t.Cfg = _cfg
- t.I18n, err = i18n.New(i18n.Glob("./locales/*/*", i18n.LoaderConfig{
- // Set custom functions per locale!
- Funcs: getFuncs,
- }), "en-US", "de-DE")
- if err != nil {
- panic(err)
- }
- if t.Cfg.Section("taldir").Key("production").MustBool(false) {
- fmt.Println("Production mode enabled")
- }
-
- navTplFile :=
t.Cfg.Section("taldir").Key("navigation").MustString("web/templates/nav.html")
- footerTplFile :=
t.Cfg.Section("taldir").Key("footer").MustString("web/templates/footer.html")
- t.Version = version
- t.BaseUrl =
t.Cfg.Section("taldir").Key("base_url").MustString("http://localhost:11000")
- t.Validators = make(map[string]Validator)
- for _, sec := range t.Cfg.Sections() {
- if !strings.HasPrefix(sec.Name(), "taldir-validator-") {
- continue
- }
- if !sec.HasKey("type") {
- log.Printf("`type` key in section `[%s]` not found,
disabling validator.\n", sec.Name())
- continue
- }
- vname := strings.TrimPrefix(sec.Name(), "taldir-validator-")
- vlandingPageTplFile :=
sec.Key("registration_page").MustString("web/templates/landing_" + vname +
".html")
- vlandingPageTpl, err :=
template.ParseFiles(vlandingPageTplFile, navTplFile, footerTplFile)
- if err != nil {
- log.Printf("`%s` template not found, disabling
validator `%s`.\n", vlandingPageTplFile, vname)
- continue
- }
- t.Validators[vname] = Validator{
- Name: vname,
- LandingPageTpl: vlandingPageTpl,
- ChallengeFee:
sec.Key("challenge_fee").MustString("KUDOS:0"),
- PaymentRequired: sec.Key("enabled").MustBool(false),
- Command: sec.Key("command").MustString(""),
- Type: ValidatorType(sec.Key("type").MustString("")),
- ValidAliasRegex:
sec.Key("valid_alias_regex").MustString(""),
- }
- }
- t.ChallengeBytes =
t.Cfg.Section("taldir").Key("challenge_bytes").MustInt(16)
- t.ValidationInitiationMax =
t.Cfg.Section("taldir").Key("validation_initiation_max").MustInt64(3)
- t.SolutionAttemptsMax =
t.Cfg.Section("taldir").Key("solution_attempt_max").MustInt(3)
-
- validationTTLStr :=
t.Cfg.Section("taldir").Key("validation_timeframe").MustString("5m")
- t.ValidPMSRegex =
t.Cfg.Section("taldir").Key("valid_payment_system_address_regex").MustString("[A-Z]+")
- t.ValidationTimeframe, err = time.ParseDuration(validationTTLStr)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
-
- retryTimeframeStr :=
t.Cfg.Section("taldir").Key("solution_attempt_timeframe").MustString("1h")
- t.SolutionTimeframe, err = time.ParseDuration(retryTimeframeStr)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
- t.MonthlyFee =
t.Cfg.Section("taldir").Key("monthly_fee").MustString("KUDOS:0")
-
- psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s
sslmode=disable",
- t.Cfg.Section("taldir-pq").Key("host").MustString("localhost"),
- t.Cfg.Section("taldir-pq").Key("port").MustInt64(5432),
- t.Cfg.Section("taldir-pq").Key("user").MustString("taldir"),
- t.Cfg.Section("taldir-pq").Key("password").MustString("secret"),
- t.Cfg.Section("taldir-pq").Key("db_name").MustString("taldir"))
- _db, err := gorm.Open(postgres.Open(psqlconn), &gorm.Config{
- Logger: logger.Default.LogMode(logger.Silent),
- })
- if err != nil {
- panic(err)
- }
- t.Db = _db
- if err := t.Db.AutoMigrate(&entry{}); err != nil {
- panic(err)
- }
- if err := t.Db.AutoMigrate(&validation{}); err != nil {
- panic(err)
- }
- if
t.Cfg.Section("taldir").Key("purge_mappings_on_startup_dangerous").MustBool(false)
{
- log.Println("DANGER Purging mappings!")
- tx := t.Db.Where("1 = 1").Delete(&entry{})
- log.Printf("Deleted %d entries.\n", tx.RowsAffected)
- }
- // Clean up validations
- validationExpStr :=
t.Cfg.Section("taldir").Key("validation_expiration").MustString("24h")
- validationExp, err := time.ParseDuration(validationExpStr)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
- go func() {
- for true {
- tx := t.Db.Where("created_at < ?",
time.Now().Add(-validationExp)).Delete(&validation{})
- log.Printf("Cleaned up %d stale validations.\n",
tx.RowsAffected)
- time.Sleep(validationExp)
- }
- }()
- validationLandingTplFile :=
t.Cfg.Section("taldir").Key("validation_landing").MustString("web/templates/validation_landing.html")
- t.ValidationTpl, err = template.ParseFiles(validationLandingTplFile,
navTplFile, footerTplFile)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
- landingTplFile :=
t.Cfg.Section("taldir").Key("landing_page").MustString("web/templates/landing.html")
- t.LandingPageTpl, err = template.ParseFiles(landingTplFile, navTplFile,
footerTplFile)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
- lookupResultTplFile :=
t.Cfg.Section("taldir").Key("lookup_result_page").MustString("web/templates/lookup_result.html")
- t.LookupResultPageTpl, err = template.ParseFiles(lookupResultTplFile,
navTplFile, footerTplFile)
- if err != nil {
- log.Fatal(err)
- os.Exit(1)
- }
- t.Salt = os.Getenv("TALDIR_SALT")
- if "" == t.Salt {
- t.Salt =
t.Cfg.Section("taldir").Key("salt").MustString("ChangeMe")
- }
- //merchURL :=
t.Cfg.Section("taldir").Key("merchant_base_url").MustString("http://merchant.taldir/")
- //merchToken :=
t.Cfg.Section("taldir").Key("merchant_token").MustString("secretAccessToken")
- //t.Merchant = merchant.NewMerchant(merchURL, merchToken)
- //merchConfig, err := t.Merchant.GetConfig()
- //if nil != err {
- // log.Fatal("Failed to get merchant config")
- // os.Exit(1)
- //}
- //registrationCost, _ := talerutil.ParseAmount(t.MonthlyFee)
- //currencySpec, currencySupported :=
merchConfig.Currencies[registrationCost.Currency]
- //for !currencySupported {
- // log.Fatalf("Currency `%s' not supported by merchant!\n",
registrationCost.Currency)
- // os.Exit(1)
- //}
- //t.CurrencySpec = currencySpec
- t.setupHandlers()
+ _cfg, err := ini.LooseLoad(cfgfile)
+ if err != nil {
+ log.Fatalf("Failed to read config: %v", err)
+ os.Exit(1)
+ }
+ t.Cfg = _cfg
+ t.I18n, err = i18n.New(i18n.Glob("./locales/*/*", i18n.LoaderConfig{
+ // Set custom functions per locale!
+ Funcs: getFuncs,
+ }), "en-US", "de-DE")
+ if err != nil {
+ panic(err)
+ }
+ if t.Cfg.Section("taldir").Key("production").MustBool(false) {
+ fmt.Println("Production mode enabled")
+ }
+
+ navTplFile :=
t.Cfg.Section("taldir").Key("navigation").MustString("web/templates/nav.html")
+ footerTplFile :=
t.Cfg.Section("taldir").Key("footer").MustString("web/templates/footer.html")
+ t.Version = version
+ t.BaseUrl =
t.Cfg.Section("taldir").Key("base_url").MustString("http://localhost:11000")
+ t.Validators = make(map[string]Validator)
+ for _, sec := range t.Cfg.Sections() {
+ if !strings.HasPrefix(sec.Name(), "taldir-validator-") {
+ continue
+ }
+ if !sec.HasKey("type") {
+ log.Printf("`type` key in section `[%s]` not found, disabling
validator.\n", sec.Name())
+ continue
+ }
+ vname := strings.TrimPrefix(sec.Name(), "taldir-validator-")
+ vlandingPageTplFile :=
sec.Key("registration_page").MustString("web/templates/landing_" + vname +
".html")
+ vlandingPageTpl, err := template.ParseFiles(vlandingPageTplFile,
navTplFile, footerTplFile)
+ if err != nil {
+ log.Printf("`%s` template not found, disabling validator `%s`.\n",
vlandingPageTplFile, vname)
+ continue
+ }
+ t.Validators[vname] = Validator{
+ Name: vname,
+ LandingPageTpl: vlandingPageTpl,
+ ChallengeFee: sec.Key("challenge_fee").MustString("KUDOS:0"),
+ PaymentRequired: sec.Key("enabled").MustBool(false),
+ Command: sec.Key("command").MustString(""),
+ Type: ValidatorType(sec.Key("type").MustString("")),
+ ValidAliasRegex: sec.Key("valid_alias_regex").MustString(""),
+ }
+ }
+ t.ChallengeBytes = t.Cfg.Section("taldir").Key("challenge_bytes").MustInt(16)
+ t.ValidationInitiationMax =
t.Cfg.Section("taldir").Key("validation_initiation_max").MustInt64(3)
+ t.SolutionAttemptsMax =
t.Cfg.Section("taldir").Key("solution_attempt_max").MustInt(3)
+
+ validationTTLStr :=
t.Cfg.Section("taldir").Key("validation_timeframe").MustString("5m")
+ t.ValidPMSRegex =
t.Cfg.Section("taldir").Key("valid_payment_system_address_regex").MustString("[A-Z]+")
+ t.ValidationTimeframe, err = time.ParseDuration(validationTTLStr)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+
+ retryTimeframeStr :=
t.Cfg.Section("taldir").Key("solution_attempt_timeframe").MustString("1h")
+ t.SolutionTimeframe, err = time.ParseDuration(retryTimeframeStr)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+ t.MonthlyFee =
t.Cfg.Section("taldir").Key("monthly_fee").MustString("KUDOS:0")
+
+ psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s
sslmode=disable",
+ t.Cfg.Section("taldir-pq").Key("host").MustString("localhost"),
+ t.Cfg.Section("taldir-pq").Key("port").MustInt64(5432),
+ t.Cfg.Section("taldir-pq").Key("user").MustString("taldir"),
+ t.Cfg.Section("taldir-pq").Key("password").MustString("secret"),
+ t.Cfg.Section("taldir-pq").Key("db_name").MustString("taldir"))
+ _db, err := gorm.Open(postgres.Open(psqlconn), &gorm.Config{
+ Logger: logger.Default.LogMode(logger.Silent),
+ })
+ if err != nil {
+ panic(err)
+ }
+ t.Db = _db
+ if err := t.Db.AutoMigrate(&entry{}); err != nil {
+ panic(err)
+ }
+ if err := t.Db.AutoMigrate(&validation{}); err != nil {
+ panic(err)
+ }
+ if
t.Cfg.Section("taldir").Key("purge_mappings_on_startup_dangerous").MustBool(false)
{
+ log.Println("DANGER Purging mappings!")
+ tx := t.Db.Where("1 = 1").Delete(&entry{})
+ log.Printf("Deleted %d entries.\n", tx.RowsAffected)
+ }
+ // Clean up validations
+ validationExpStr :=
t.Cfg.Section("taldir").Key("validation_expiration").MustString("24h")
+ validationExp, err := time.ParseDuration(validationExpStr)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+ go func() {
+ for true {
+ tx := t.Db.Where("created_at < ?",
time.Now().Add(-validationExp)).Delete(&validation{})
+ log.Printf("Cleaned up %d stale validations.\n", tx.RowsAffected)
+ time.Sleep(validationExp)
+ }
+ }()
+ validationLandingTplFile :=
t.Cfg.Section("taldir").Key("validation_landing").MustString("web/templates/validation_landing.html")
+ t.ValidationTpl, err = template.ParseFiles(validationLandingTplFile,
navTplFile, footerTplFile)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+ landingTplFile :=
t.Cfg.Section("taldir").Key("landing_page").MustString("web/templates/landing.html")
+ t.LandingPageTpl, err = template.ParseFiles(landingTplFile, navTplFile,
footerTplFile)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+ lookupResultTplFile :=
t.Cfg.Section("taldir").Key("lookup_result_page").MustString("web/templates/lookup_result.html")
+ t.LookupResultPageTpl, err = template.ParseFiles(lookupResultTplFile,
navTplFile, footerTplFile)
+ if err != nil {
+ log.Fatal(err)
+ os.Exit(1)
+ }
+ t.Salt = os.Getenv("TALDIR_SALT")
+ if "" == t.Salt {
+ t.Salt = t.Cfg.Section("taldir").Key("salt").MustString("ChangeMe")
+ }
+ //merchURL :=
t.Cfg.Section("taldir").Key("merchant_base_url").MustString("http://merchant.taldir/")
+ //merchToken :=
t.Cfg.Section("taldir").Key("merchant_token").MustString("secretAccessToken")
+ //t.Merchant = merchant.NewMerchant(merchURL, merchToken)
+ //merchConfig, err := t.Merchant.GetConfig()
+ //if nil != err {
+ // log.Fatal("Failed to get merchant config")
+ // os.Exit(1)
+ //}
+ //registrationCost, _ := talerutil.ParseAmount(t.MonthlyFee)
+ //currencySpec, currencySupported :=
merchConfig.Currencies[registrationCost.Currency]
+ //for !currencySupported {
+ // log.Fatalf("Currency `%s' not supported by merchant!\n",
registrationCost.Currency)
+ // os.Exit(1)
+ //}
+ //t.CurrencySpec = currencySpec
+ t.setupHandlers()
}
diff --git a/web/templates/landing_email.html b/web/templates/landing_email.html
index 26b92e2..efd752a 100644
--- a/web/templates/landing_email.html
+++ b/web/templates/landing_email.html
@@ -15,9 +15,9 @@
{{if .error}}
<div class="container pt-5">
<div id="ebanner" class="alert alert-danger" role="alert">
- <h4 class="alert-heading">An error occured!</h4>
+ <h4 class="alert-heading">Error</h4>
<hr>
- <p class="mb-0">{{.error}}.</p>
+ <p class="mb-0">{{.error}}</p>
</div>
</div>
{{end}}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.