From 8f83e04564f93010d33589de9d1ca3600c981e25 Mon Sep 17 00:00:00 2001 From: Peter Rounce Date: Wed, 2 Aug 2023 18:54:07 +0000 Subject: [PATCH] internalapi backward compatibility --- db/db.go | 59 +++++++++++ internalapi/createboltcard.go | 38 +------ internalapi/createboltcardwithpin.go | 153 +++++++++++++++++++++++++++ main.go | 1 + sql/create_db.sql | 2 +- 5 files changed, 217 insertions(+), 36 deletions(-) create mode 100644 internalapi/createboltcardwithpin.go diff --git a/db/db.go b/db/db.go index 4894203..29824fd 100644 --- a/db/db.go +++ b/db/db.go @@ -781,6 +781,65 @@ func Get_card_name_count(card_name string) (card_count int, err error) { } func Insert_card(one_time_code string, k0_auth_key string, k2_cmac_key string, k3 string, k4 string, + tx_limit_sats int, day_limit_sats int, lnurlw_enable bool, card_name string, uid_privacy bool, + allow_neg_bal_ptr bool) error { + + lnurlw_enable_yn := "N" + if lnurlw_enable { + lnurlw_enable_yn = "Y" + } + + uid_privacy_yn := "N" + if uid_privacy { + uid_privacy_yn = "Y" + } + + allow_neg_bal_yn := "N" + if allow_neg_bal_ptr { + allow_neg_bal_yn = "Y" + } + + db, err := open() + if err != nil { + return err + } + defer db.Close() + + // ensure any cards with the same card_name are wiped + + sqlStatement := `UPDATE cards SET` + + ` lnurlw_enable = 'N', lnurlp_enable = 'N', email_enable = 'N', wiped = 'Y'` + + ` WHERE card_name = $1;` + res, err := db.Exec(sqlStatement, card_name) + if err != nil { + return err + } + + // insert a new record into cards + + sqlStatement = `INSERT INTO cards` + + ` (one_time_code, k0_auth_key, k2_cmac_key, k3, k4, uid, last_counter_value,` + + ` lnurlw_request_timeout_sec, tx_limit_sats, day_limit_sats, lnurlw_enable,` + + ` one_time_code_used, card_name, uid_privacy, allow_negative_balance)` + + ` VALUES ($1, $2, $3, $4, $5, '', 0, 60, $6, $7, $8, 'N', $9, $10, $11);` + res, err = db.Exec(sqlStatement, one_time_code, k0_auth_key, k2_cmac_key, k3, k4, + tx_limit_sats, day_limit_sats, lnurlw_enable_yn, card_name, uid_privacy_yn, + allow_neg_bal_yn) + if err != nil { + return err + } + count, err := res.RowsAffected() + if err != nil { + return err + } + if count != 1 { + return errors.New("not one card record inserted") + } + + return nil +} + +func Insert_card_with_pin(one_time_code string, k0_auth_key string, k2_cmac_key string, k3 string, k4 string, tx_limit_sats int, day_limit_sats int, lnurlw_enable bool, card_name string, uid_privacy bool, allow_neg_bal_ptr bool, pin_enable bool, pin_number string, pin_limit_sats int) error { diff --git a/internalapi/createboltcard.go b/internalapi/createboltcard.go index ea9f913..e0e1eb3 100644 --- a/internalapi/createboltcard.go +++ b/internalapi/createboltcard.go @@ -1,8 +1,6 @@ package internalapi import ( - "crypto/rand" - "encoding/hex" "github.com/boltcard/boltcard/db" "github.com/boltcard/boltcard/resp_err" log "github.com/sirupsen/logrus" @@ -11,16 +9,7 @@ import ( "strings" ) -func random_hex() string { - b := make([]byte, 16) - _, err := rand.Read(b) - if err != nil { - log.Warn(err.Error()) - return "" - } - - return hex.EncodeToString(b) -} +// random_hex() from Createboltcardwithpin used here func Createboltcard(w http.ResponseWriter, r *http.Request) { if db.Get_setting("FUNCTION_INTERNAL_API") != "ENABLE" { @@ -83,33 +72,12 @@ func Createboltcard(w http.ResponseWriter, r *http.Request) { return } - pin_enable_flag_str := r.URL.Query().Get("enable_pin") - pin_enable_flag, err := strconv.ParseBool(pin_enable_flag_str) - if err != nil { - msg := "updateboltcard: enable_pin is not a valid boolean" - log.Warn(msg) - resp_err.Write_message(w, msg) - return - } - - pin_number := r.URL.Query().Get("pin_number") - - pin_limit_sats_str := r.URL.Query().Get("pin_limit_sats") - pin_limit_sats, err := strconv.Atoi(pin_limit_sats_str) - if err != nil { - msg := "updateboltcard: pin_limit_sats is not a valid integer" - log.Warn(msg) - resp_err.Write_message(w, msg) - return - } - // log the request log.WithFields(log.Fields{ "card_name": card_name, "tx_max": tx_max, "day_max": day_max, "enable": enable_flag, "uid_privacy": uid_privacy_flag, - "allow_neg_bal": allow_neg_bal_flag, "enable_pin": pin_enable_flag, - "pin_number": pin_number, "pin_limit_sats": pin_limit_sats}).Info("createboltcard API request") + "allow_neg_bal": allow_neg_bal_flag}).Info("createboltcard API request") // create the keys @@ -123,7 +91,7 @@ func Createboltcard(w http.ResponseWriter, r *http.Request) { err = db.Insert_card(one_time_code, k0_auth_key, k2_cmac_key, k3, k4, tx_max, day_max, enable_flag, card_name, - uid_privacy_flag, allow_neg_bal_flag, pin_enable_flag, pin_number, pin_limit_sats) + uid_privacy_flag, allow_neg_bal_flag) if err != nil { log.Warn(err.Error()) return diff --git a/internalapi/createboltcardwithpin.go b/internalapi/createboltcardwithpin.go new file mode 100644 index 0000000..64d9efd --- /dev/null +++ b/internalapi/createboltcardwithpin.go @@ -0,0 +1,153 @@ +package internalapi + +import ( + "crypto/rand" + "encoding/hex" + "github.com/boltcard/boltcard/db" + "github.com/boltcard/boltcard/resp_err" + log "github.com/sirupsen/logrus" + "net/http" + "strconv" + "strings" +) + +func random_hex() string { + b := make([]byte, 16) + _, err := rand.Read(b) + if err != nil { + log.Warn(err.Error()) + return "" + } + + return hex.EncodeToString(b) +} + +func Createboltcardwithpin(w http.ResponseWriter, r *http.Request) { + if db.Get_setting("FUNCTION_INTERNAL_API") != "ENABLE" { + msg := "createboltcardwithpin: internal API function is not enabled" + log.Debug(msg) + resp_err.Write_message(w, msg) + return + } + + tx_max_str := r.URL.Query().Get("tx_max") + tx_max, err := strconv.Atoi(tx_max_str) + if err != nil { + msg := "createboltcardwithpin: tx_max is not a valid integer" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + day_max_str := r.URL.Query().Get("day_max") + day_max, err := strconv.Atoi(day_max_str) + if err != nil { + msg := "createboltcardwithpin: day_max is not a valid integer" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + enable_flag_str := r.URL.Query().Get("enable") + enable_flag, err := strconv.ParseBool(enable_flag_str) + if err != nil { + msg := "createboltcardwithpin: enable is not a valid boolean" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + card_name := r.URL.Query().Get("card_name") + if card_name == "" { + msg := "createboltcardwithpin: the card name must be set" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + uid_privacy_flag_str := r.URL.Query().Get("uid_privacy") + uid_privacy_flag, err := strconv.ParseBool(uid_privacy_flag_str) + if err != nil { + msg := "createboltcardwithpin: uid_privacy is not a valid boolean" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + allow_neg_bal_flag_str := r.URL.Query().Get("allow_neg_bal") + allow_neg_bal_flag, err := strconv.ParseBool(allow_neg_bal_flag_str) + if err != nil { + msg := "createboltcardwithpin: allow_neg_bal is not a valid boolean" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + pin_enable_flag_str := r.URL.Query().Get("enable_pin") + pin_enable_flag, err := strconv.ParseBool(pin_enable_flag_str) + if err != nil { + msg := "createboltcardwithpin: enable_pin is not a valid boolean" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + pin_number := r.URL.Query().Get("pin_number") + + pin_limit_sats_str := r.URL.Query().Get("pin_limit_sats") + pin_limit_sats, err := strconv.Atoi(pin_limit_sats_str) + if err != nil { + msg := "createboltcardwithpin: pin_limit_sats is not a valid integer" + log.Warn(msg) + resp_err.Write_message(w, msg) + return + } + + // log the request + + log.WithFields(log.Fields{ + "card_name": card_name, "tx_max": tx_max, "day_max": day_max, + "enable": enable_flag, "uid_privacy": uid_privacy_flag, + "allow_neg_bal": allow_neg_bal_flag, "enable_pin": pin_enable_flag, + "pin_number": pin_number, "pin_limit_sats": pin_limit_sats}).Info("createboltcardwithpin API request") + + // create the keys + + one_time_code := random_hex() + k0_auth_key := random_hex() + k2_cmac_key := random_hex() + k3 := random_hex() + k4 := random_hex() + + // create the new card record + + err = db.Insert_card_with_pin(one_time_code, k0_auth_key, k2_cmac_key, k3, k4, + tx_max, day_max, enable_flag, card_name, + uid_privacy_flag, allow_neg_bal_flag, pin_enable_flag, pin_number, pin_limit_sats) + if err != nil { + log.Warn(err.Error()) + return + } + + // return the URI + one_time_code + + hostdomain := db.Get_setting("HOST_DOMAIN") + url := "" + if strings.HasSuffix(hostdomain, ".onion") { + url = "http://" + hostdomain + "/new?a=" + one_time_code + } else { + url = "https://" + hostdomain + "/new?a=" + one_time_code + } + + // log the response + + log.WithFields(log.Fields{ + "card_name": card_name, "url": url}).Info("createboltcard API response") + + jsonData := []byte(`{"status":"OK",` + + `"url":"` + url + `"}`) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(jsonData) +} diff --git a/main.go b/main.go index d665ba7..d4e7148 100644 --- a/main.go +++ b/main.go @@ -53,6 +53,7 @@ func main() { internal_router.Path("/ping").Methods("GET").HandlerFunc(internalapi.Internal_ping) internal_router.Path("/createboltcard").Methods("GET").HandlerFunc(internalapi.Createboltcard) + internal_router.Path("/createboltcardwithpin").Methods("GET").HandlerFunc(internalapi.Createboltcardwithpin) internal_router.Path("/updateboltcard").Methods("GET").HandlerFunc(internalapi.Updateboltcard) internal_router.Path("/updateboltcardwithpin").Methods("GET").HandlerFunc(internalapi.Updateboltcardwithpin) internal_router.Path("/wipeboltcard").Methods("GET").HandlerFunc(internalapi.Wipeboltcard) diff --git a/sql/create_db.sql b/sql/create_db.sql index 6021a33..9cd6135 100644 --- a/sql/create_db.sql +++ b/sql/create_db.sql @@ -30,7 +30,7 @@ CREATE TABLE cards ( allow_negative_balance CHAR(1) NOT NULL DEFAULT 'N', pin_enable CHAR(1) NOT NULL DEFAULT 'N', pin_number CHAR(4) NOT NULL DEFAULT '0000', - pin_limit_sats INT NOT NULL, + pin_limit_sats INT NOT NULL DEFAULT 0, wiped CHAR(1) NOT NULL DEFAULT 'N', PRIMARY KEY(card_id) );