From 0feb013c78a7039ddbf26141b54ec56d26eb4ed2 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 5 Sep 2024 20:35:51 +0100 Subject: [PATCH] Ensure handler init when state and cache is available --- go-vise | 2 +- internal/handlers/ussd/menuhandler.go | 200 ++++++++++++++++++++------ internal/utils/filehandler.go | 13 -- services/registration/Makefile | 2 +- 4 files changed, 161 insertions(+), 56 deletions(-) delete mode 100644 internal/utils/filehandler.go diff --git a/go-vise b/go-vise index 326bdb5..2bddc36 160000 --- a/go-vise +++ b/go-vise @@ -1 +1 @@ -Subproject commit 326bdb5018ae81ee493371b56bd4564a8b35da59 +Subproject commit 2bddc363f20210ab019eec29d8ba4104d147e9b7 diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 92c401e..c43cb3b 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -75,6 +75,7 @@ func (fm *FlagManager) GetFlag(label string) (uint32, error) { } type Handlers struct { + pe *persist.Persister st *state.State ca cache.Memory userdataStore db.Db @@ -84,9 +85,14 @@ type Handlers struct { } func NewHandlers(appFlags *asm.FlagParser, pe *persist.Persister, userdataStore db.Db) (*Handlers, error) { + if pe == nil { + return nil, fmt.Errorf("cannot create handler with nil persister") + } + if userdataStore == nil { + return nil, fmt.Errorf("cannot create handler with nil userdata store") + } h := &Handlers{ - st: pe.State, - ca: pe.GetMemory(), + pe: pe, userdataStore: userdataStore, flagManager: appFlags, accountFileHandler: utils.NewAccountFileHandler(userdataStore), @@ -104,9 +110,28 @@ func isValidPIN(pin string) bool { return match } +func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var r resource.Result + if h.pe == nil { + logg.WarnCtxf(ctx, "handler init called before it is ready or more than once", "state", h.st, "cache", h.ca) + return r, nil + } + h.st = h.pe.GetState() + h.ca = h.pe.GetMemory() + if h.st == nil || h.ca == nil { + logg.ErrorCtxf(ctx, "perister fail in handler", "state", h.st, "cache", h.ca) + return r, fmt.Errorf("cannot get state and memory for handler") + } + h.pe = nil + return r, nil +} + // SetLanguage sets the language across the menu func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } inputStr := string(input) switch inputStr { @@ -152,8 +177,10 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r // creates an account on the API, // sets the default values and flags func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} - var err error + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") @@ -178,7 +205,10 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) // SavePin persists the user's PIN choice into the filesystem func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") @@ -195,7 +225,7 @@ func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resou res.FlagReset = append(res.FlagReset, flag_incorrect_pin) - err := utils.WriteEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN)) + err = utils.WriteEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN)) if err != nil { return res, nil } @@ -205,7 +235,10 @@ func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resou // SetResetSingleEdit sets and resets flags to allow gradual editing of profile information. func (h *Handlers) SetResetSingleEdit(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } menuOption := string(input) flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") @@ -232,7 +265,10 @@ func (h *Handlers) SetResetSingleEdit(ctx context.Context, sym string, input []b // If similar, it sets the USERFLAG_PIN_SET flag allowing the user // to access the main menu func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin") flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") @@ -267,8 +303,11 @@ func codeFromCtx(ctx context.Context) string { } // SaveFirstname updates the first name in a JSON data file with the provided input. -func (h *Handlers) SaveFirstname(cxt context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} +func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) (resource.Result, error) { + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } if len(input) > 0 { //name := string(input) //key := []byte(FirstName) @@ -280,8 +319,11 @@ func (h *Handlers) SaveFirstname(cxt context.Context, sym string, input []byte) } // SaveFamilyname updates the family name in a JSON data file with the provided input. -func (h *Handlers) SaveFamilyname(cxt context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} +func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) (resource.Result, error) { + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } if len(input) > 0 { //secondname := string(input) //key := []byte(FamilyName) @@ -293,8 +335,11 @@ func (h *Handlers) SaveFamilyname(cxt context.Context, sym string, input []byte) } // SaveYOB updates the Year of Birth(YOB) in a JSON data file with the provided input. -func (h *Handlers) SaveYob(cxt context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} +func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } yob := string(input) if len(yob) == 4 { //yob := string(input) @@ -307,8 +352,11 @@ func (h *Handlers) SaveYob(cxt context.Context, sym string, input []byte) (resou } // SaveLocation updates the location in a JSON data file with the provided input. -func (h *Handlers) SaveLocation(cxt context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} +func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) (resource.Result, error) { + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } if len(input) > 0 { //location := string(input) //key := []byte(Location) @@ -322,7 +370,10 @@ func (h *Handlers) SaveLocation(cxt context.Context, sym string, input []byte) ( // SaveGender updates the gender in a JSON data file with the provided input. func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } if len(input) > 0 { gender := string(input) switch gender { @@ -342,7 +393,10 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re // SaveOfferings updates the offerings(goods and services provided by the user) in a JSON data file with the provided input. func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } if len(input) > 0 { //offerings := string(input) //key := []byte(Offerings) @@ -354,7 +408,10 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) // ResetAllowUpdate resets the allowupdate flag that allows a user to update profile data. func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") @@ -364,7 +421,10 @@ func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byt // ResetAccountAuthorized resets the account authorization flag after a successful PIN entry. func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") @@ -374,7 +434,10 @@ func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input // CheckIdentifier retrieves the PublicKey from the JSON data file. func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } //publicKey, err := h.db.Fetch([]byte(PublicKeyKey)) // if err != nil { // return res, err @@ -386,7 +449,10 @@ func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte // Authorize attempts to unlock the next sequential nodes by verifying the provided PIN against the already set PIN. // It sets the required flags that control the flow. func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") @@ -422,7 +488,10 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res // ResetIncorrectPin resets the incorrect pin flag after a new PIN attempt. func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") @@ -433,7 +502,10 @@ func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []by // CheckAccountStatus queries the API using the TrackingId and sets flags // based on the account status func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_account_success, _ := h.flagManager.GetFlag("flag_account_success") flag_account_pending, _ := h.flagManager.GetFlag("flag_account_pending") @@ -475,7 +547,10 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b // Quit displays the Thank you message and exits the menu func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") @@ -490,12 +565,15 @@ func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource // VerifyYob verifies the length of the given input func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format") date := string(input) - _, err := strconv.Atoi(date) + _, err = strconv.Atoi(date) if err != nil { // If conversion fails, input is not numeric res.FlagSet = append(res.FlagSet, flag_incorrect_date_format) @@ -513,7 +591,10 @@ func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (res // ResetIncorrectYob resets the incorrect date format flag after a new attempt func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format") @@ -524,7 +605,11 @@ func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []by // CheckBalance retrieves the balance from the API using the "PublicKey" and sets // the balance as the result content func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } + // publicKey, err := h.db.Fetch([]byte(PublicKeyKey)) sessionId, ok := ctx.Value("SessionId").(string) if !ok { @@ -544,7 +629,10 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( // ValidateRecipient validates that the given input is a valid phone number. func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } recipient := string(input) flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") @@ -571,7 +659,10 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by // TransactionReset resets the previous transaction data (Recipient and Amount) // as well as the invalid flags func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") @@ -592,7 +683,10 @@ func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byt // ResetTransactionAmount resets the transaction amount and invalid flag func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") @@ -609,7 +703,10 @@ func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input // MaxAmount gets the current balance from the API and sets it as // the result content. func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } // publicKey, err := h.db.Fetch([]byte(PublicKeyKey)) // if err != nil { // return res, err @@ -628,7 +725,10 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res // ValidateAmount ensures that the given input is a valid amount and that // it is not more than the current balance. func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") @@ -692,7 +792,10 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) // GetRecipient returns the transaction recipient from a JSON data file. func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } // recipient, err := h.db.Fetch([]byte(Recipient)) // if err != nil { // return res, err @@ -705,7 +808,10 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) ( // GetSender retrieves the public key from the Gdbm Db func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } // publicKey, err := h.db.Fetch([]byte(PublicKeyKey)) // if err != nil { // return res, err @@ -718,7 +824,10 @@ func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (res // GetAmount retrieves the amount from teh Gdbm Db func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } // amount, err := h.db.Fetch([]byte(Amount)) // if err != nil { // return res, err @@ -731,7 +840,10 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res // QuickWithBalance retrieves the balance for a given public key from the custodial balance API endpoint before // gracefully exiting the session. func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") @@ -754,7 +866,10 @@ func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte // InitiateTransaction returns a confirmation and resets the transaction data // on the JSON file. func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } code := codeFromCtx(ctx) l := gotext.NewLocale(translationDir, code) l.AddDomain("default") @@ -787,7 +902,10 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input [] // GetProfileInfo retrieves and formats the profile information of a user from a Gdbm backed storage. func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) { - res := resource.Result{} + res, err := h.Init(ctx, sym, input) + if err != nil { + return res, err + } // Define default values defaultValue := "Not provided" diff --git a/internal/utils/filehandler.go b/internal/utils/filehandler.go deleted file mode 100644 index 8b11e29..0000000 --- a/internal/utils/filehandler.go +++ /dev/null @@ -1,13 +0,0 @@ -package utils - - - - -type AccountFileHandlerInterface interface { - EnsureFileExists() error - ReadAccountData() (map[string]string, error) - WriteAccountData(data map[string]string) error -} - - - diff --git a/services/registration/Makefile b/services/registration/Makefile index 1863b0b..af8b8c1 100644 --- a/services/registration/Makefile +++ b/services/registration/Makefile @@ -4,7 +4,7 @@ TXTS = $(wildcard ./*.txt.orig) # Rule to build .bin files from .vis files %.vis: - go run ../../go-vise/dev/asm -f pp.csv $(basename $@).vis > $(basename $@).bin + go run ../../go-vise/dev/asm/main.go -f pp.csv $(basename $@).vis > $(basename $@).bin @echo "Built $(basename $@).bin from $(basename $@).vis" # Rule to copy .orig files to .txt