From 72d5c186dd7a04b738262263ed5c785103f5e88f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:18:40 +0300 Subject: [PATCH 01/86] add admin privilege flag --- services/registration/pp.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/registration/pp.csv b/services/registration/pp.csv index ec0d8c1..cee8d13 100644 --- a/services/registration/pp.csv +++ b/services/registration/pp.csv @@ -17,3 +17,5 @@ flag,flag_incorrect_date_format,23,this is set when the given year of birth is i flag,flag_incorrect_voucher,24,this is set when the selected voucher is invalid flag,flag_api_call_error,25,this is set when communication to an external service fails flag,flag_no_active_voucher,26,this is set when a user does not have an active voucher +flag,flag_admin_privilege,27,this is set when a user has admin privileges. + From 0cc0bdf9f71836301879eb068f22c96382f0bf96 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:19:35 +0300 Subject: [PATCH 02/86] add pin reset for others nodes --- services/registration/enter_others_new_pin | 1 + services/registration/enter_others_new_pin.vis | 8 ++++++++ services/registration/invalid_others_pin | 1 + services/registration/invalid_others_pin.vis | 5 +++++ services/registration/no_admin_privilege | 1 + services/registration/no_admin_privilege.vis | 5 +++++ services/registration/others_pin_mismatch | 1 + services/registration/others_pin_mismatch.vis | 5 +++++ services/registration/pin_management.vis | 3 +-- services/registration/pin_reset_result | 1 + services/registration/pin_reset_result.vis | 7 +++++++ 11 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 services/registration/enter_others_new_pin create mode 100644 services/registration/enter_others_new_pin.vis create mode 100644 services/registration/invalid_others_pin create mode 100644 services/registration/invalid_others_pin.vis create mode 100644 services/registration/no_admin_privilege create mode 100644 services/registration/no_admin_privilege.vis create mode 100644 services/registration/others_pin_mismatch create mode 100644 services/registration/others_pin_mismatch.vis create mode 100644 services/registration/pin_reset_result create mode 100644 services/registration/pin_reset_result.vis diff --git a/services/registration/enter_others_new_pin b/services/registration/enter_others_new_pin new file mode 100644 index 0000000..52ae664 --- /dev/null +++ b/services/registration/enter_others_new_pin @@ -0,0 +1 @@ +Please enter new PIN for: {{.retrieve_blocked_number}} \ No newline at end of file diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis new file mode 100644 index 0000000..aa2818d --- /dev/null +++ b/services/registration/enter_others_new_pin.vis @@ -0,0 +1,8 @@ +LOAD retrieve_blocked_number 0 +MAP retrieve_blocked_number +MOUT back 0 +HALT +INCMP _ 0 +LOAD verify_new_pin 0 +RELOAD verify_new_pin +INCMP * confirm_others_new_pin diff --git a/services/registration/invalid_others_pin b/services/registration/invalid_others_pin new file mode 100644 index 0000000..acdf45f --- /dev/null +++ b/services/registration/invalid_others_pin @@ -0,0 +1 @@ +The PIN you have entered is invalid.Please try a 4 digit number instead. \ No newline at end of file diff --git a/services/registration/invalid_others_pin.vis b/services/registration/invalid_others_pin.vis new file mode 100644 index 0000000..d218e6d --- /dev/null +++ b/services/registration/invalid_others_pin.vis @@ -0,0 +1,5 @@ +MOUT retry 1 +MOUT quit 9 +HALT +INCMP enter_others_new_pin 1 +INCMP quit 9 diff --git a/services/registration/no_admin_privilege b/services/registration/no_admin_privilege new file mode 100644 index 0000000..27901dc --- /dev/null +++ b/services/registration/no_admin_privilege @@ -0,0 +1 @@ +You do not have privileges to perform this action diff --git a/services/registration/no_admin_privilege.vis b/services/registration/no_admin_privilege.vis new file mode 100644 index 0000000..3cf1e4c --- /dev/null +++ b/services/registration/no_admin_privilege.vis @@ -0,0 +1,5 @@ +MOUT quit 9 +MOUT back 0 +HALT +INCMP pin_management 0 +INCMP quit 9 diff --git a/services/registration/others_pin_mismatch b/services/registration/others_pin_mismatch new file mode 100644 index 0000000..deb9fe5 --- /dev/null +++ b/services/registration/others_pin_mismatch @@ -0,0 +1 @@ +The PIN you have entered is not a match diff --git a/services/registration/others_pin_mismatch.vis b/services/registration/others_pin_mismatch.vis new file mode 100644 index 0000000..37b3deb --- /dev/null +++ b/services/registration/others_pin_mismatch.vis @@ -0,0 +1,5 @@ +MOUT retry 1 +MOUT quit 9 +HALT +INCMP _ 1 +INCMP quit 9 diff --git a/services/registration/pin_management.vis b/services/registration/pin_management.vis index 3b33dad..b196a50 100644 --- a/services/registration/pin_management.vis +++ b/services/registration/pin_management.vis @@ -1,8 +1,7 @@ MOUT change_pin 1 MOUT reset_pin 2 -MOUT guard_pin 3 MOUT back 0 HALT INCMP _ 0 INCMP old_pin 1 - +INCMP enter_other_number 2 diff --git a/services/registration/pin_reset_result b/services/registration/pin_reset_result new file mode 100644 index 0000000..60554b9 --- /dev/null +++ b/services/registration/pin_reset_result @@ -0,0 +1 @@ +PIN reset request for {{.retrieve_blocked_number}} was successful \ No newline at end of file diff --git a/services/registration/pin_reset_result.vis b/services/registration/pin_reset_result.vis new file mode 100644 index 0000000..ed71200 --- /dev/null +++ b/services/registration/pin_reset_result.vis @@ -0,0 +1,7 @@ +LOAD retrieve_blocked_number 0 +MAP retrieve_blocked_number +MOUT back 0 +MOUT quit 9 +HALT +INCMP pin_management 0 +INCMP quit 9 From 3de46cef5e2758b228ea49bf597d2627185f3aa1 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:45:08 +0300 Subject: [PATCH 03/86] setup pin reset nodes --- services/registration/confirm_others_new_pin | 1 + services/registration/confirm_others_new_pin.vis | 13 +++++++++++++ services/registration/confirm_pin_change.vis | 2 -- services/registration/enter_other_number | 1 + services/registration/enter_other_number.vis | 9 +++++++++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 services/registration/confirm_others_new_pin create mode 100644 services/registration/confirm_others_new_pin.vis create mode 100644 services/registration/enter_other_number create mode 100644 services/registration/enter_other_number.vis diff --git a/services/registration/confirm_others_new_pin b/services/registration/confirm_others_new_pin new file mode 100644 index 0000000..46c3275 --- /dev/null +++ b/services/registration/confirm_others_new_pin @@ -0,0 +1 @@ +Please confirm new PIN for: {{.retrieve_blocked_number}} \ No newline at end of file diff --git a/services/registration/confirm_others_new_pin.vis b/services/registration/confirm_others_new_pin.vis new file mode 100644 index 0000000..be6734f --- /dev/null +++ b/services/registration/confirm_others_new_pin.vis @@ -0,0 +1,13 @@ +LOAD retrieve_blocked_number 0 +MAP retrieve_blocked_number +CATCH invalid_others_pin flag_valid_pin 0 +LOAD save_temporary_pin 6 +RELOAD save_temporary_pin +CATCH pin_reset_result flag_account_authorized 1 +MOUT back 0 +HALT +INCMP _ 0 +LOAD check_pin_mismatch 0 +RELOAD check_pin_mismatch +CATCH others_pin_mismatch flag_pin_mismatch 1 +INCMP pin_entry * diff --git a/services/registration/confirm_pin_change.vis b/services/registration/confirm_pin_change.vis index 7691e01..cf485a1 100644 --- a/services/registration/confirm_pin_change.vis +++ b/services/registration/confirm_pin_change.vis @@ -3,5 +3,3 @@ MOUT back 0 HALT INCMP _ 0 INCMP * pin_reset_success - - diff --git a/services/registration/enter_other_number b/services/registration/enter_other_number new file mode 100644 index 0000000..1c4a481 --- /dev/null +++ b/services/registration/enter_other_number @@ -0,0 +1 @@ +Enter other's phone number: \ No newline at end of file diff --git a/services/registration/enter_other_number.vis b/services/registration/enter_other_number.vis new file mode 100644 index 0000000..41c711a --- /dev/null +++ b/services/registration/enter_other_number.vis @@ -0,0 +1,9 @@ +CATCH no_admin_privilege flag_admin_privilege 0 +LOAD reset_account_authorized 6 +RELOAD reset_account_authorized +MOUT back 0 +HALT +INCMP _ 0 +LOAD validate_blocked_number 0 +RELOAD validate_blocked_number +INCMP enter_others_new_pin * From e4c2f644f378ffc15429a2614aebdcb12ce142f4 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:47:56 +0300 Subject: [PATCH 04/86] define a key to hold number during pin reset --- internal/utils/db.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/utils/db.go b/internal/utils/db.go index 45e7681..57f3289 100644 --- a/internal/utils/db.go +++ b/internal/utils/db.go @@ -28,6 +28,7 @@ const ( DATA_ACTIVE_SYM DATA_TEMPORARY_BAL DATA_ACTIVE_BAL + DATA_BLOCKED_NUMBER ) func typToBytes(typ DataTyp) []byte { From 26073c8000c030cb6d03766bac6dffe851aca88f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:49:20 +0300 Subject: [PATCH 05/86] define handler functions required to reset others pin --- internal/handlers/handlerservice.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 311e694..a30f1b2 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -54,7 +54,7 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { } func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { - ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore,accountService) + ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, accountService) if err != nil { return nil, err } @@ -98,6 +98,10 @@ func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceIn ls.DbRs.AddLocalFunc("get_vouchers", ussdHandlers.GetVoucherList) ls.DbRs.AddLocalFunc("view_voucher", ussdHandlers.ViewVoucher) ls.DbRs.AddLocalFunc("set_voucher", ussdHandlers.SetVoucher) + ls.DbRs.AddLocalFunc("reset_valid_pin", ussdHandlers.ResetValidPin) + ls.DbRs.AddLocalFunc("check_pin_mismatch", ussdHandlers.CheckPinMisMatch) + ls.DbRs.AddLocalFunc("validate_blocked_number", ussdHandlers.ValidateBlockedNumber) + ls.DbRs.AddLocalFunc("retrieve_blocked_number", ussdHandlers.RetrieveBlockedNumber) return ussdHandlers, nil } From aec0abb2b632af7cda2296a8eb8bcb8b5e6aaac6 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 16:34:33 +0300 Subject: [PATCH 06/86] setup an admin flag --- cmd/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/main.go b/cmd/main.go index 21ca0c3..e79176c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -33,10 +33,12 @@ func main() { var size uint var sessionId string var database string + var isAdmin bool var engineDebug bool flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&database, "db", "gdbm", "database to be used") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") + flag.BoolVar(&isAdmin, "admin", false, "if user has admin previleges") flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.UintVar(&size, "s", 160, "max size of output") flag.Parse() @@ -46,6 +48,7 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Database", database) + ctx = context.WithValue(ctx, "Admin", isAdmin) pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ From b97965193bb53185221a77d846e3d40e6d7ca005 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 16:37:23 +0300 Subject: [PATCH 07/86] add pin reset for others handling --- internal/handlers/ussd/menuhandler.go | 118 ++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 9 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f4d279b..ae50724 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -27,11 +27,12 @@ import ( ) var ( - logg = logging.NewVanilla().WithDomain("ussdmenuhandler") - scriptDir = path.Join("services", "registration") - translationDir = path.Join(scriptDir, "locale") - okResponse *api.OKResponse - errResponse *api.ErrResponse + logg = logging.NewVanilla().WithDomain("ussdmenuhandler") + scriptDir = path.Join("services", "registration") + translationDir = path.Join(scriptDir, "locale") + PINChangePrivilege byte = 1 + okResponse *api.OKResponse + errResponse *api.ErrResponse ) // FlagManager handles centralized flag management @@ -98,20 +99,41 @@ func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { return h } +func setAdminPrevilege(ctx context.Context, store utils.DataStore) error { + var err error + + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return fmt.Errorf("missing session") + } + prefixdb := storage.NewSubPrefixDb(store, []byte("acl")) + err = prefixdb.Put(ctx, []byte(sessionId), []byte("1")) + if err != nil { + return err + } + return nil +} + 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 + store := h.userdataStore + err := setAdminPrevilege(ctx, store) + if err != nil { + return r, fmt.Errorf("failed to set previlege level") + } logg.DebugCtxf(ctx, "handler has been initialized", "state", h.st, "cache", h.ca) @@ -189,6 +211,26 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) return res, nil } +func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byte) (resource.Result, error) { + res := resource.Result{} + flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + store := h.userdataStore + temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + if err != nil { + return res, err + } + if bytes.Equal(temporaryPin, input) { + res.FlagReset = append(res.FlagReset, flag_pin_mismatch) + } else { + res.FlagSet = append(res.FlagSet, flag_pin_mismatch) + } + return res, nil +} + func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { res := resource.Result{} _, ok := ctx.Value("SessionId").(string) @@ -284,7 +326,6 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte if err != nil { return res, err } - if bytes.Equal(input, temporaryPin) { res.FlagSet = []uint32{flag_valid_pin} res.FlagReset = []uint32{flag_pin_mismatch} @@ -444,6 +485,14 @@ func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byt return res, nil } +// ResetAllowUpdate resets the allowupdate flag that allows a user to update profile data. +func (h *Handlers) ResetValidPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin") + res.FlagReset = append(res.FlagReset, flag_valid_pin) + return res, nil +} + // 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) { var res resource.Result @@ -501,6 +550,7 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res return res, nil } } else { + fmt.Println("Authorizing the account else") return res, nil } return res, nil @@ -522,17 +572,37 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b flag_account_success, _ := h.flagManager.GetFlag("flag_account_success") flag_account_pending, _ := h.flagManager.GetFlag("flag_account_pending") flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") + flag_admin_privilege, _ := h.flagManager.GetFlag("flag_admin_privilege") sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") } + isAdmin, _ := ctx.Value("Admin").(bool) store := h.userdataStore publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) if err != nil { return res, err } + if isAdmin { + setAdminPrevilege(ctx, store) + } + prefixdb := storage.NewSubPrefixDb(store, []byte("acl")) + accessLevel, err := prefixdb.Get(ctx, []byte(sessionId)) + if err != nil { + if !db.IsNotFound(err) { + return res, nil + } + } + isPrevileged := bytes.Equal(accessLevel, []byte("1")) + + if isPrevileged { + //Set Admin privilege Flag + res.FlagSet = append(res.FlagSet, flag_admin_privilege) + } + okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey)) + if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) return res, err @@ -588,7 +658,6 @@ func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (res var err error flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format") - date := string(input) _, err = strconv.Atoi(date) if err != nil { @@ -694,6 +763,22 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input return res, nil } +func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + var err error + store := h.userdataStore + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + blockedNumber := string(input) + err = store.WriteEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) + if err != nil { + return res, nil + } + return res, nil +} + // 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) { var res resource.Result @@ -865,6 +950,22 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) ( return res, nil } +// RetrieveBlockedNumber gets the current number during the pin reset for other's is in progress. +func (h *Handlers) RetrieveBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + store := h.userdataStore + blockedNumber, _ := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + + res.Content = string(blockedNumber) + + return res, nil +} + // GetSender returns the sessionId (phoneNumber) func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -1102,7 +1203,6 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) if err != nil { return res, nil } - err = prefixdb.Put(ctx, []byte("bal"), []byte(voucherBalanceList)) if err != nil { return res, nil From e338ce00257316f6a9d107d81bfde9043bdea0e7 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 13:14:49 +0300 Subject: [PATCH 08/86] load and reload only after input --- services/registration/enter_familyname.vis | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/registration/enter_familyname.vis b/services/registration/enter_familyname.vis index b9fe7b0..5a684ed 100644 --- a/services/registration/enter_familyname.vis +++ b/services/registration/enter_familyname.vis @@ -1,9 +1,8 @@ CATCH incorrect_pin flag_incorrect_pin 1 CATCH profile_update_success flag_allow_update 1 -LOAD save_familyname 0 -RELOAD save_familyname MOUT back 0 HALT +LOAD save_familyname 0 RELOAD save_familyname INCMP _ 0 INCMP pin_entry * From ca13d9155c000a615a89fb6d0fce44765e67c12d Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 13:15:22 +0300 Subject: [PATCH 09/86] replace _ with explicit back node --- services/registration/pin_management.vis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registration/pin_management.vis b/services/registration/pin_management.vis index b196a50..c0adc5c 100644 --- a/services/registration/pin_management.vis +++ b/services/registration/pin_management.vis @@ -2,6 +2,6 @@ MOUT change_pin 1 MOUT reset_pin 2 MOUT back 0 HALT -INCMP _ 0 +INCMP my_account 0 INCMP old_pin 1 INCMP enter_other_number 2 From c9bb93ede6c0deaba60868c4eb2f39a717371f59 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 13:15:41 +0300 Subject: [PATCH 10/86] create a simple admin store for phone numbers --- internal/utils/adminstore.go | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 internal/utils/adminstore.go diff --git a/internal/utils/adminstore.go b/internal/utils/adminstore.go new file mode 100644 index 0000000..98241a6 --- /dev/null +++ b/internal/utils/adminstore.go @@ -0,0 +1,68 @@ +package utils + +import ( + "bufio" + "os" + "strconv" +) + +type AdminStore struct { + filePath string +} + +// Creates a new Admin store +func NewAdminStore(filePath string) *AdminStore { + return &AdminStore{filePath: filePath} +} + +// Seed saves a list of phonumbers with admin privileges +func (as *AdminStore) Seed() error { + adminNumbers := []int64{254705136690, 123456789012, 987654321098} + file, err := os.Create(as.filePath) + if err != nil { + return err + } + defer file.Close() + + writer := bufio.NewWriter(file) + for _, num := range adminNumbers { + _, err := writer.WriteString(strconv.FormatInt(num, 10) + "\n") + if err != nil { + return err + } + } + return writer.Flush() +} + + +func (as *AdminStore) load() ([]int64, error) { + file, err := os.Open(as.filePath) + if err != nil { + return nil, err + } + defer file.Close() + + var numbers []int64 + scanner := bufio.NewScanner(file) + for scanner.Scan() { + num, err := strconv.ParseInt(scanner.Text(), 10, 64) + if err != nil { + return nil, err + } + numbers = append(numbers, num) + } + return numbers, scanner.Err() +} + +func (as *AdminStore) IsAdmin(phoneNumber int64) (bool, error) { + phoneNumbers, err := as.load() + if err != nil { + return false, err + } + for _, phonenumber := range phoneNumbers { + if phonenumber == phoneNumber { + return true, nil + } + } + return false, nil +} From 41da099933a9ee36605258179c305bc5965720d8 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 13:24:13 +0300 Subject: [PATCH 11/86] remove the admin flag,setup an admin store --- cmd/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index e79176c..4d23011 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -15,6 +15,7 @@ import ( "git.grassecon.net/urdt/ussd/internal/handlers" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/internal/utils" ) var ( @@ -33,12 +34,10 @@ func main() { var size uint var sessionId string var database string - var isAdmin bool var engineDebug bool flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&database, "db", "gdbm", "database to be used") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") - flag.BoolVar(&isAdmin, "admin", false, "if user has admin previleges") flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.UintVar(&size, "s", 160, "max size of output") flag.Parse() @@ -48,9 +47,11 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Database", database) - ctx = context.WithValue(ctx, "Admin", isAdmin) pfp := path.Join(scriptDir, "pp.csv") + as := utils.NewAdminStore("admin_numbers.txt") + as.Seed() + cfg := engine.Config{ Root: "root", SessionId: sessionId, From d83962c0ba7481327d529f612df96288f09327ff Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 14:26:24 +0300 Subject: [PATCH 12/86] load admin numbers defined in the .env --- internal/utils/adminstore.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/internal/utils/adminstore.go b/internal/utils/adminstore.go index 98241a6..ddd6bd9 100644 --- a/internal/utils/adminstore.go +++ b/internal/utils/adminstore.go @@ -2,8 +2,12 @@ package utils import ( "bufio" + "log" "os" "strconv" + "strings" + + "git.grassecon.net/urdt/ussd/initializers" ) type AdminStore struct { @@ -15,9 +19,18 @@ func NewAdminStore(filePath string) *AdminStore { return &AdminStore{filePath: filePath} } -// Seed saves a list of phonumbers with admin privileges +// Seed initializes a list of phonenumbers with admin privileges func (as *AdminStore) Seed() error { - adminNumbers := []int64{254705136690, 123456789012, 987654321098} + var adminNumbers []int64 + + numbersEnv := initializers.GetEnv("ADMIN_NUMBERS", "") + for _, numStr := range strings.Split(numbersEnv, ",") { + if num, err := strconv.ParseInt(strings.TrimSpace(numStr), 10, 64); err == nil { + adminNumbers = append(adminNumbers, num) + } else { + log.Printf("Skipping invalid number: %s", numStr) + } + } file, err := os.Create(as.filePath) if err != nil { return err @@ -34,7 +47,6 @@ func (as *AdminStore) Seed() error { return writer.Flush() } - func (as *AdminStore) load() ([]int64, error) { file, err := os.Open(as.filePath) if err != nil { From 5fd3eb3c292f5640cd556a1063e1ab5f220d3e23 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 14:28:58 +0300 Subject: [PATCH 13/86] set admin privilege flag --- internal/handlers/ussd/menuhandler.go | 55 ++++++++------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index ae50724..d397eff 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -99,21 +99,6 @@ func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { return h } -func setAdminPrevilege(ctx context.Context, store utils.DataStore) error { - var err error - - sessionId, ok := ctx.Value("SessionId").(string) - if !ok { - return fmt.Errorf("missing session") - } - prefixdb := storage.NewSubPrefixDb(store, []byte("acl")) - err = prefixdb.Put(ctx, []byte(sessionId), []byte("1")) - if err != nil { - return err - } - return nil -} - func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) { var r resource.Result if h.pe == nil { @@ -124,16 +109,24 @@ func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource h.st = h.pe.GetState() h.ca = h.pe.GetMemory() + sessionId, _ := ctx.Value("SessionId").(string) + flag_admin_privilege, _ := h.flagManager.GetFlag("flag_admin_privilege") + + number, _ := strconv.ParseInt(sessionId, 10, 64) + as := utils.NewAdminStore("admin_numbers.txt") + isAdmin, _ := as.IsAdmin(number) + + if isAdmin { + r.FlagSet = append(r.FlagSet, flag_admin_privilege) + } else { + r.FlagReset = append(r.FlagReset, flag_admin_privilege) + } + 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 - store := h.userdataStore - err := setAdminPrevilege(ctx, store) - if err != nil { - return r, fmt.Errorf("failed to set previlege level") - } logg.DebugCtxf(ctx, "handler has been initialized", "state", h.st, "cache", h.ca) @@ -403,6 +396,7 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou if !ok { return res, fmt.Errorf("missing session") } + if len(input) == 4 { yob := string(input) store := h.userdataStore @@ -550,7 +544,6 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res return res, nil } } else { - fmt.Println("Authorizing the account else") return res, nil } return res, nil @@ -572,37 +565,19 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b flag_account_success, _ := h.flagManager.GetFlag("flag_account_success") flag_account_pending, _ := h.flagManager.GetFlag("flag_account_pending") flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") - flag_admin_privilege, _ := h.flagManager.GetFlag("flag_admin_privilege") sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") } - isAdmin, _ := ctx.Value("Admin").(bool) + store := h.userdataStore publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) if err != nil { return res, err } - if isAdmin { - setAdminPrevilege(ctx, store) - } - prefixdb := storage.NewSubPrefixDb(store, []byte("acl")) - accessLevel, err := prefixdb.Get(ctx, []byte(sessionId)) - if err != nil { - if !db.IsNotFound(err) { - return res, nil - } - } - isPrevileged := bytes.Equal(accessLevel, []byte("1")) - - if isPrevileged { - //Set Admin privilege Flag - res.FlagSet = append(res.FlagSet, flag_admin_privilege) - } okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey)) - if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) return res, err From 124049c92453ff6db90f91b2fe0fce4554a2061a Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 14:32:17 +0300 Subject: [PATCH 14/86] add admin number defination in env --- .env.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.env.example b/.env.example index ab370a7..4d86f8b 100644 --- a/.env.example +++ b/.env.example @@ -16,3 +16,7 @@ CREATE_ACCOUNT_URL=http://localhost:5003/api/v2/account/create TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/ BALANCE_URL=https://custodial.sarafu.africa/api/account/status/ TRACK_URL=http://localhost:5003/api/v2/account/status + + +#numbers with privileges to reset others pin +ADMIN_NUMBERS=254051722XXX,255012221XXX \ No newline at end of file From e96c8743004550e0738494b9cd3d0899d7be7885 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 15:02:40 +0300 Subject: [PATCH 15/86] repeat same node on invalid option input --- services/registration/pin_management.vis | 1 + 1 file changed, 1 insertion(+) diff --git a/services/registration/pin_management.vis b/services/registration/pin_management.vis index c0adc5c..5eb7d5a 100644 --- a/services/registration/pin_management.vis +++ b/services/registration/pin_management.vis @@ -5,3 +5,4 @@ HALT INCMP my_account 0 INCMP old_pin 1 INCMP enter_other_number 2 +INCMP . * From 449f90c95b6a4f41bd2d8c1501a99ae39d052fc7 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:17:03 +0300 Subject: [PATCH 16/86] add flag to catch unregistred numbers --- services/registration/pp.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registration/pp.csv b/services/registration/pp.csv index cee8d13..406cc22 100644 --- a/services/registration/pp.csv +++ b/services/registration/pp.csv @@ -18,4 +18,4 @@ flag,flag_incorrect_voucher,24,this is set when the selected voucher is invalid flag,flag_api_call_error,25,this is set when communication to an external service fails flag,flag_no_active_voucher,26,this is set when a user does not have an active voucher flag,flag_admin_privilege,27,this is set when a user has admin privileges. - +flag,flag_unregistered_number,28,this is set when an unregistered phonenumber tries to perform an action From 6998c30dd1614077ddcf36ac5d1fb4ab3a4ff338 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:18:01 +0300 Subject: [PATCH 17/86] add node to handle unregistered phone numbers --- services/registration/unregistered_number | 1 + services/registration/unregistered_number.vis | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 services/registration/unregistered_number create mode 100644 services/registration/unregistered_number.vis diff --git a/services/registration/unregistered_number b/services/registration/unregistered_number new file mode 100644 index 0000000..9cc33d7 --- /dev/null +++ b/services/registration/unregistered_number @@ -0,0 +1 @@ +The number you have entered is either not registered with Sarafu or is invalid. \ No newline at end of file diff --git a/services/registration/unregistered_number.vis b/services/registration/unregistered_number.vis new file mode 100644 index 0000000..f7a6a9c --- /dev/null +++ b/services/registration/unregistered_number.vis @@ -0,0 +1,7 @@ +LOAD reset_unregistered_number 0 +RELOAD reset_unregistered_number +MOUT retry 1 +MOUT quit 9 +HALT +INCMP enter_other_number 1 +INCMP quit 9 From 534d75631836a50bf00ebe194b33c6d061726853 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:18:39 +0300 Subject: [PATCH 18/86] catch unregistred phone numbers --- services/registration/enter_others_new_pin.vis | 1 + 1 file changed, 1 insertion(+) diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis index aa2818d..1577ff1 100644 --- a/services/registration/enter_others_new_pin.vis +++ b/services/registration/enter_others_new_pin.vis @@ -1,3 +1,4 @@ +CATCH unregistered_number flag_unregistered_number 1 LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number MOUT back 0 From 91b85af11a223cb66de5b6cc2af900296556b3b0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:34:34 +0300 Subject: [PATCH 19/86] add reset unregistered number --- internal/handlers/handlerservice.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index a30f1b2..b4cd592 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -102,6 +102,7 @@ func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceIn ls.DbRs.AddLocalFunc("check_pin_mismatch", ussdHandlers.CheckPinMisMatch) ls.DbRs.AddLocalFunc("validate_blocked_number", ussdHandlers.ValidateBlockedNumber) ls.DbRs.AddLocalFunc("retrieve_blocked_number", ussdHandlers.RetrieveBlockedNumber) + ls.DbRs.AddLocalFunc("reset_unregistered_number", ussdHandlers.ResetUnregisteredNumber) return ussdHandlers, nil } From 106983a3940fc0b2066e0486fd1b47dcd1239345 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:35:01 +0300 Subject: [PATCH 20/86] use explicit back to node --- services/registration/enter_other_number.vis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registration/enter_other_number.vis b/services/registration/enter_other_number.vis index 41c711a..7f413da 100644 --- a/services/registration/enter_other_number.vis +++ b/services/registration/enter_other_number.vis @@ -3,7 +3,7 @@ LOAD reset_account_authorized 6 RELOAD reset_account_authorized MOUT back 0 HALT -INCMP _ 0 LOAD validate_blocked_number 0 RELOAD validate_blocked_number +INCMP pin_management 0 INCMP enter_others_new_pin * From d0ad6395b5670501b543e61e2a5ef2c8c5acf2ca Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 17:35:42 +0300 Subject: [PATCH 21/86] add check for unregistered phone numbers --- internal/handlers/ussd/menuhandler.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index d395a8b..715a654 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -748,15 +748,35 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input return res, nil } +func (h *Handlers) ResetUnregisteredNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") + res.FlagReset = append(res.FlagReset, flag_unregistered_number) + return res, nil +} + func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result var err error + + flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") + store := h.userdataStore sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") } blockedNumber := string(input) + _, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY) + if err != nil { + if db.IsNotFound(err) { + logg.Printf(logging.LVL_INFO, "Invalid or unregistered number") + res.FlagSet = append(res.FlagSet, flag_unregistered_number) + return res, nil + } else { + return res, err + } + } err = store.WriteEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) if err != nil { return res, nil From f37483e2f04d4fa4ead95223ff2c0acc33518ff8 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 22:15:31 +0300 Subject: [PATCH 22/86] use _ for back navigation --- services/registration/unregistered_number.vis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/registration/unregistered_number.vis b/services/registration/unregistered_number.vis index f7a6a9c..114113f 100644 --- a/services/registration/unregistered_number.vis +++ b/services/registration/unregistered_number.vis @@ -3,5 +3,5 @@ RELOAD reset_unregistered_number MOUT retry 1 MOUT quit 9 HALT -INCMP enter_other_number 1 +INCMP _ 1 INCMP quit 9 From 7597b96daec3367a8a09dff0ee24f95a616107a2 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 22:16:34 +0300 Subject: [PATCH 23/86] remove catch for unregistered number --- services/registration/enter_others_new_pin.vis | 1 - 1 file changed, 1 deletion(-) diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis index 1577ff1..aa2818d 100644 --- a/services/registration/enter_others_new_pin.vis +++ b/services/registration/enter_others_new_pin.vis @@ -1,4 +1,3 @@ -CATCH unregistered_number flag_unregistered_number 1 LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number MOUT back 0 From 5a0563df94b67fade2498e8f37eef91f82a95da4 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 22:17:43 +0300 Subject: [PATCH 24/86] group regex,check for valid number against the regex --- internal/handlers/ussd/menuhandler.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 715a654..70510ee 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -35,6 +35,12 @@ var ( backOption = []byte("0") ) +// Define the regex patterns as constants +const ( + phoneRegex = `(\(\d{3}\)\s?|\d{3}[-.\s]?)?\d{3}[-.\s]?\d{4}` + pinPattern = `^\d{4}$` +) + // FlagManager handles centralized flag management type FlagManager struct { parser *asm.FlagParser @@ -82,15 +88,17 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService s return h, nil } -// Define the regex pattern as a constant -const pinPattern = `^\d{4}$` - // isValidPIN checks whether the given input is a 4 digit number func isValidPIN(pin string) bool { match, _ := regexp.MatchString(pinPattern, pin) return match } +func isValidPhoneNumber(phonenumber string) bool { + match, _ := regexp.MatchString(phoneRegex, phonenumber) + return match +} + func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { if h.pe != nil { panic("persister already set") @@ -255,7 +263,6 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt } flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") - accountPIN := string(input) // Validate that the PIN is a 4-digit number @@ -768,6 +775,9 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input } blockedNumber := string(input) _, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY) + if !isValidPhoneNumber(blockedNumber) { + return res, nil + } if err != nil { if db.IsNotFound(err) { logg.Printf(logging.LVL_INFO, "Invalid or unregistered number") From 0a97f610a47746c25cc7748ebbf29937e3bc11a2 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 29 Oct 2024 22:23:22 +0300 Subject: [PATCH 25/86] catch unregistred number --- services/registration/enter_other_number.vis | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/registration/enter_other_number.vis b/services/registration/enter_other_number.vis index 7f413da..e2fa243 100644 --- a/services/registration/enter_other_number.vis +++ b/services/registration/enter_other_number.vis @@ -1,9 +1,10 @@ CATCH no_admin_privilege flag_admin_privilege 0 -LOAD reset_account_authorized 6 +LOAD reset_account_authorized 0 RELOAD reset_account_authorized MOUT back 0 HALT -LOAD validate_blocked_number 0 +INCMP _ 0 +LOAD validate_blocked_number 20 RELOAD validate_blocked_number -INCMP pin_management 0 +CATCH unregistered_number flag_unregistered_number 1 INCMP enter_others_new_pin * From dd764a2e24514b9799e78973c7ccb80c510f1593 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 01:28:55 +0000 Subject: [PATCH 26/86] Export db datatypes,tools --- {internal/utils => common}/db.go | 2 +- internal/handlers/ussd/menuhandler.go | 108 ++++++++++----------- internal/handlers/ussd/menuhandler_test.go | 97 +++++++++--------- internal/testutil/mocks/userdbmock.go | 6 +- internal/utils/userStore.go | 14 +-- 5 files changed, 114 insertions(+), 113 deletions(-) rename {internal/utils => common}/db.go (97%) diff --git a/internal/utils/db.go b/common/db.go similarity index 97% rename from internal/utils/db.go rename to common/db.go index 2c1e6fa..349d3aa 100644 --- a/internal/utils/db.go +++ b/common/db.go @@ -1,4 +1,4 @@ -package utils +package common import ( "encoding/binary" diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dae4236..e2bcfaf 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -151,9 +151,9 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r trackingId := okResponse.Result["trackingId"].(string) publicKey := okResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: trackingId, - utils.DATA_PUBLIC_KEY: publicKey, + data := map[common.DataTyp]string{ + common.DATA_TRACKING_ID: trackingId, + common.DATA_PUBLIC_KEY: publicKey, } store := h.userdataStore for key, value := range data { @@ -166,7 +166,7 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r if err != nil { return err } - err = store.WriteEntry(ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)) + err = store.WriteEntry(ctx, publicKeyNormalized, common.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)) if err != nil { return err } @@ -186,7 +186,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) return res, fmt.Errorf("missing session") } store := h.userdataStore - _, err = store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_CREATED) + _, err = store.ReadEntry(ctx, sessionId, common.DATA_ACCOUNT_CREATED) if err != nil { if db.IsNotFound(err) { logg.Printf(logging.LVL_INFO, "Creating an account because it doesn't exist") @@ -242,7 +242,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagReset = append(res.FlagReset, flag_incorrect_pin) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(accountPIN)) if err != nil { return res, err } @@ -259,7 +259,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN) if err != nil { return res, err } @@ -268,7 +268,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt } else { res.FlagSet = append(res.FlagSet, flag_pin_mismatch) } - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, err } @@ -290,7 +290,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_PIN) if err != nil { return res, err } @@ -303,7 +303,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte res.FlagSet = []uint32{flag_pin_mismatch} } - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, err } @@ -335,7 +335,7 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) } firstName := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)) if err != nil { return res, err } @@ -358,7 +358,7 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) } familyName := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)) if err != nil { return res, err } @@ -380,7 +380,7 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou if len(input) == 4 { yob := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(yob)) + err = store.WriteEntry(ctx, sessionId, common.DATA_YOB, []byte(yob)) if err != nil { return res, err } @@ -403,7 +403,7 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( } location := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) + err = store.WriteEntry(ctx, sessionId, common.DATA_LOCATION, []byte(location)) if err != nil { return res, err } @@ -426,7 +426,7 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re } gender := strings.Split(symbol, "_")[1] store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) + err = store.WriteEntry(ctx, sessionId, common.DATA_GENDER, []byte(gender)) if err != nil { return res, nil } @@ -445,7 +445,7 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) if len(input) > 0 { offerings := string(input) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)) + err = store.WriteEntry(ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)) if err != nil { return res, nil } @@ -481,7 +481,7 @@ func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, _ := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) res.Content = string(publicKey) @@ -502,7 +502,7 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") store := h.userdataStore - AccountPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN) + AccountPin, err := store.ReadEntry(ctx, sessionId, common.DATA_ACCOUNT_PIN) if err != nil { return res, err } @@ -548,7 +548,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b return res, fmt.Errorf("missing session") } store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, err } @@ -654,7 +654,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( store := h.userdataStore // get the active sym and active balance - activeSym, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { if db.IsNotFound(err) { balance := "0.00" @@ -665,7 +665,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( return res, err } - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -687,7 +687,7 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input balanceType := strings.Split(symbol, "_")[0] store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, err } @@ -737,7 +737,7 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by return res, nil } store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(recipient)) + err = store.WriteEntry(ctx, sessionId, common.DATA_RECIPIENT, []byte(recipient)) if err != nil { return res, nil } @@ -760,12 +760,12 @@ func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byt flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte("")) if err != nil { return res, nil } - err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_RECIPIENT, []byte("")) if err != nil { return res, nil } @@ -787,7 +787,7 @@ func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte("")) if err != nil { return res, nil } @@ -809,7 +809,7 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res } store := h.userdataStore - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -834,7 +834,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) var balanceValue float64 // retrieve the active balance - activeBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL) + activeBal, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_BAL) if err != nil { return res, err } @@ -860,7 +860,7 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) // Format the amount with 2 decimal places before saving formattedAmount := fmt.Sprintf("%.2f", inputAmount) - err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(formattedAmount)) + err = store.WriteEntry(ctx, sessionId, common.DATA_AMOUNT, []byte(formattedAmount)) if err != nil { return res, err } @@ -878,7 +878,7 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) ( return res, fmt.Errorf("missing session") } store := h.userdataStore - recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT) + recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT) res.Content = string(recipient) @@ -910,12 +910,12 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res store := h.userdataStore // retrieve the active symbol - activeSym, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, err := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { return res, err } - amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT) + amount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT) res.Content = fmt.Sprintf("%s %s", string(amount), string(activeSym)) @@ -939,11 +939,11 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input [] // Use the amount, recipient and sender to call the API and initialize the transaction store := h.userdataStore - amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT) + amount, _ := store.ReadEntry(ctx, sessionId, common.DATA_AMOUNT) - recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT) + recipient, _ := store.ReadEntry(ctx, sessionId, common.DATA_RECIPIENT) - activeSym, _ := store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + activeSym, _ := store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) res.Content = l.Get("Your request has been sent. %s will receive %s %s from %s.", string(recipient), string(amount), string(activeSym), string(sessionId)) @@ -983,12 +983,12 @@ func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) } store := h.userdataStore // Retrieve user data as strings with fallback to defaultValue - firstName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FIRST_NAME)) - familyName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FAMILY_NAME)) - yob := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_YOB)) - gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_GENDER)) - location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_LOCATION)) - offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_OFFERINGS)) + firstName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_FIRST_NAME)) + familyName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_FAMILY_NAME)) + yob := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_YOB)) + gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_GENDER)) + location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_LOCATION)) + offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, common.DATA_OFFERINGS)) // Construct the full name name := defaultValue @@ -1045,11 +1045,11 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by flag_no_active_voucher, _ := h.flagManager.GetFlag("flag_no_active_voucher") // check if the user has an active sym - _, err = store.ReadEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM) + _, err = store.ReadEntry(ctx, sessionId, common.DATA_ACTIVE_SYM) if err != nil { if db.IsNotFound(err) { - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, nil } @@ -1072,12 +1072,12 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by defaultBal := firstVoucher.Balance // set the active symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(defaultSym)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(defaultSym)) if err != nil { return res, err } // set the active balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(defaultBal)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(defaultBal)) if err != nil { return res, err } @@ -1103,7 +1103,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) } store := h.userdataStore - publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) + publicKey, err := store.ReadEntry(ctx, sessionId, common.DATA_PUBLIC_KEY) if err != nil { return res, nil } @@ -1207,11 +1207,11 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r // If a match is found, write the temporary sym and balance if matchedSymbol != "" && matchedBalance != "" { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte(matchedSymbol)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte(matchedSymbol)) if err != nil { return res, err } - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte(matchedBalance)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte(matchedBalance)) if err != nil { return res, err } @@ -1269,34 +1269,34 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re } // get the current temporary symbol - temporarySym, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM) + temporarySym, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM) if err != nil { return res, err } // get the current temporary balance - temporaryBal, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL) + temporaryBal, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL) if err != nil { return res, err } // set the active symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(temporarySym)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(temporarySym)) if err != nil { return res, err } // set the active balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(temporaryBal)) + err = store.WriteEntry(ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(temporaryBal)) if err != nil { return res, err } // reset the temporary symbol - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte("")) if err != nil { return res, err } // reset the temporary balance - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte("")) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte("")) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 0b70e80..b83fa61 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,7 +19,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -119,12 +118,12 @@ func TestCreateAccount(t *testing.T) { } publicKey := tt.serverResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), - utils.DATA_PUBLIC_KEY: publicKey, + data := map[common.DataTyp]string{ + common.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), + common.DATA_PUBLIC_KEY: publicKey, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) mockCreateAccountService.On("CreateAccount").Return(tt.serverResponse, nil) for key, value := range data { @@ -135,7 +134,7 @@ func TestCreateAccount(t *testing.T) { t.Fatal(err) } - mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) + mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, common.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) // Call the method you want to test res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) @@ -181,7 +180,7 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -209,7 +208,7 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -269,7 +268,7 @@ func TestSaveTemporaryPin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -295,7 +294,7 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_YOB, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_YOB, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -323,7 +322,7 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_LOCATION, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_LOCATION, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -351,7 +350,7 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -413,10 +412,10 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { - expectedKey := utils.DATA_GENDER + expectedKey := common.DATA_GENDER mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store @@ -433,9 +432,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) } }) } @@ -469,7 +468,7 @@ func TestCheckIdentifier(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) + mockStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) // Create the Handlers instance with the mock store h := &Handlers{ @@ -519,8 +518,8 @@ func TestGetAmount(t *testing.T) { activeSym := "SRF" // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return([]byte(amount), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_AMOUNT).Return([]byte(amount), nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -546,7 +545,7 @@ func TestGetRecipient(t *testing.T) { recepient := "0xcasgatweksalw1018221" // Set up the expected behavior of the mock - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return([]byte(recepient), nil) + mockStore.On("ReadEntry", ctx, sessionId, common.DATA_RECIPIENT).Return([]byte(recepient), nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -828,7 +827,7 @@ func TestAuthorize(t *testing.T) { // Define session ID and mock data sessionId := "session123" - typ := utils.DATA_ACCOUNT_PIN + typ := common.DATA_ACCOUNT_PIN h := &Handlers{ userdataStore: mockDataStore, @@ -1011,7 +1010,7 @@ func TestVerifyCreatePin(t *testing.T) { }, } - typ := utils.DATA_TEMPORARY_PIN + typ := common.DATA_TEMPORARY_PIN for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1020,7 +1019,7 @@ func TestVerifyCreatePin(t *testing.T) { mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(firstSetPin), nil) // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) // Call the method under test res, err := h.VerifyCreatePin(ctx, "verify_create_pin", []byte(tt.input)) @@ -1141,11 +1140,11 @@ func TestCheckAccountStatus(t *testing.T) { status := tt.response.Result.Transaction.Status // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.input, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() // Call the method under test res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) @@ -1201,8 +1200,8 @@ func TestTransactionReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_RECIPIENT, []byte("")).Return(nil) // Call the method under test res, _ := h.TransactionReset(ctx, "transaction_reset", tt.input) @@ -1257,7 +1256,7 @@ func TestResetInvalidAmount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, []byte("")).Return(nil) // Call the method under test res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", tt.input) @@ -1320,9 +1319,9 @@ func TestInitiateTransaction(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return(tt.Amount, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return(tt.Recipient, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_AMOUNT).Return(tt.Amount, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_RECIPIENT).Return(tt.Recipient, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) // Call the method under test res, _ := h.InitiateTransaction(ctx, "transaction_reset_amount", tt.input) @@ -1502,10 +1501,10 @@ func TestValidateAmount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Mock behavior for active balance retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) // Mock behavior for storing the amount (if valid) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_AMOUNT, tt.input).Return(nil).Maybe() // Call the method under test res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input) @@ -1559,7 +1558,7 @@ func TestValidateRecipient(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, tt.input).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_RECIPIENT, tt.input).Return(nil) // Create the Handlers instance with the mock flag manager h := &Handlers{ @@ -1613,8 +1612,8 @@ func TestCheckBalance(t *testing.T) { } // Mock for user with active sym - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) + mockDataStore.On("ReadEntry", ctx, tt.sessionId, common.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) + mockDataStore.On("ReadEntry", ctx, tt.sessionId, common.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) res, err := h.CheckBalance(ctx, "check_balance", []byte("")) @@ -1648,13 +1647,13 @@ func TestGetProfile(t *testing.T) { tests := []struct { name string languageCode string - keys []utils.DataTyp + keys []common.DataTyp profileInfo []string result resource.Result }{ { name: "Test with full profile information in eng", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "eng", result: resource.Result{ @@ -1666,7 +1665,7 @@ func TestGetProfile(t *testing.T) { }, { name: "Test with with profile information in swa ", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "swa", result: resource.Result{ @@ -1678,7 +1677,7 @@ func TestGetProfile(t *testing.T) { }, { name: "Test with with profile information with language that is not yet supported", - keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, + keys: []common.DataTyp{common.DATA_FAMILY_NAME, common.DATA_FIRST_NAME, common.DATA_GENDER, common.DATA_OFFERINGS, common.DATA_LOCATION, common.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "nor", result: resource.Result{ @@ -1802,9 +1801,9 @@ func TestConfirmPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) @@ -1829,12 +1828,12 @@ func TestSetVoucher(t *testing.T) { temporaryBal := []byte("tempBal") // Set expectations for the mock data store - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM).Return(temporarySym, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL).Return(temporaryBal, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM, temporarySym).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL, temporaryBal).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL, []byte("")).Return(nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_SYM).Return(temporarySym, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_BAL).Return(temporaryBal, nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_SYM, temporarySym).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_BAL, temporaryBal).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_SYM, []byte("")).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_BAL, []byte("")).Return(nil) h := &Handlers{ userdataStore: mockDataStore, @@ -1919,7 +1918,7 @@ func TestFetchCustodialBalances(t *testing.T) { } // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) // Call the method diff --git a/internal/testutil/mocks/userdbmock.go b/internal/testutil/mocks/userdbmock.go index ff3f18d..7892179 100644 --- a/internal/testutil/mocks/userdbmock.go +++ b/internal/testutil/mocks/userdbmock.go @@ -4,7 +4,7 @@ import ( "context" "git.defalsify.org/vise.git/db" - "git.grassecon.net/urdt/ussd/internal/utils" + "git.grassecon.net/urdt/ussd/common" "github.com/stretchr/testify/mock" ) @@ -13,12 +13,12 @@ type MockUserDataStore struct { mock.Mock } -func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ utils.DataTyp) ([]byte, error) { +func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { args := m.Called(ctx, sessionId, typ) return args.Get(0).([]byte), args.Error(1) } -func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ utils.DataTyp, value []byte) error { +func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { args := m.Called(ctx, sessionId, typ, value) return args.Error(0) } diff --git a/internal/utils/userStore.go b/internal/utils/userStore.go index a1485b1..13682b7 100644 --- a/internal/utils/userStore.go +++ b/internal/utils/userStore.go @@ -3,13 +3,15 @@ package utils import ( "context" + "git.grassecon.net/urdt/ussd/common" + "git.defalsify.org/vise.git/db" ) type DataStore interface { db.Db - ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) - WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error + ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) + WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error } type UserDataStore struct { @@ -17,16 +19,16 @@ type UserDataStore struct { } // ReadEntry retrieves an entry from the store based on the provided parameters. -func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { +func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := PackKey(typ, []byte(sessionId)) + k := common.PackKey(typ, []byte(sessionId)) return store.Get(ctx, k) } -func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { +func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := PackKey(typ, []byte(sessionId)) + k := common.PackKey(typ, []byte(sessionId)) return store.Put(ctx, k, value) } From c95b97cb148114aed46a8aa84da8ec9faf2dcaee Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 01:45:38 +0000 Subject: [PATCH 27/86] Export user data store --- .../utils/userStore.go => common/user_store.go | 16 +++++++--------- internal/handlers/ussd/menuhandler.go | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) rename internal/utils/userStore.go => common/user_store.go (55%) diff --git a/internal/utils/userStore.go b/common/user_store.go similarity index 55% rename from internal/utils/userStore.go rename to common/user_store.go index 13682b7..8d982ab 100644 --- a/internal/utils/userStore.go +++ b/common/user_store.go @@ -1,17 +1,15 @@ -package utils +package common import ( "context" - "git.grassecon.net/urdt/ussd/common" - "git.defalsify.org/vise.git/db" ) type DataStore interface { db.Db - ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) - WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error + ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) + WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error } type UserDataStore struct { @@ -19,16 +17,16 @@ type UserDataStore struct { } // ReadEntry retrieves an entry from the store based on the provided parameters. -func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ common.DataTyp) ([]byte, error) { +func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := common.PackKey(typ, []byte(sessionId)) + k := PackKey(typ, []byte(sessionId)) return store.Get(ctx, k) } -func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ common.DataTyp, value []byte) error { +func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) - k := common.PackKey(typ, []byte(sessionId)) + k := PackKey(typ, []byte(sessionId)) return store.Put(ctx, k, value) } diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index e2bcfaf..303bea9 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -63,7 +63,7 @@ type Handlers struct { pe *persist.Persister st *state.State ca cache.Memory - userdataStore utils.DataStore + userdataStore common.DataStore flagManager *asm.FlagParser accountService server.AccountServiceInterface } @@ -72,7 +72,7 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService s if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } - userDb := &utils.UserDataStore{ + userDb := &common.UserDataStore{ Db: userdataStore, } h := &Handlers{ From b404ae95fbfa4fdec0b7c84e7c7486618a754eca Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:30:38 +0300 Subject: [PATCH 28/86] setup an admin store based on fs --- internal/utils/adminstore.go | 111 ++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/internal/utils/adminstore.go b/internal/utils/adminstore.go index ddd6bd9..43a3bfd 100644 --- a/internal/utils/adminstore.go +++ b/internal/utils/adminstore.go @@ -1,80 +1,85 @@ package utils import ( - "bufio" - "log" + "context" + "encoding/json" "os" - "strconv" - "strings" - "git.grassecon.net/urdt/ussd/initializers" + "git.defalsify.org/vise.git/db" + fsdb "git.defalsify.org/vise.git/db/fs" + "git.defalsify.org/vise.git/logging" ) -type AdminStore struct { - filePath string +var ( + logg = logging.NewVanilla().WithDomain("adminstore") +) + +type Admin struct { + PhoneNumber string `json:"phonenumber"` } -// Creates a new Admin store -func NewAdminStore(filePath string) *AdminStore { - return &AdminStore{filePath: filePath} +type Config struct { + Admins []Admin `json:"admins"` +} + +type AdminStore struct { + ctx context.Context + fsStore db.Db +} + +func NewAdminStore(ctx context.Context, fileName string) (*AdminStore, error) { + fsStore, err := getFsStore(ctx, fileName) + if err != nil { + return nil, err + } + return &AdminStore{ctx: ctx, fsStore: fsStore}, nil +} + +func getFsStore(ctx context.Context, connectStr string) (db.Db, error) { + fsStore := fsdb.NewFsDb() + err := fsStore.Connect(ctx, connectStr) + fsStore.SetPrefix(db.DATATYPE_USERDATA) + if err != nil { + return nil, err + } + return fsStore, nil } // Seed initializes a list of phonenumbers with admin privileges func (as *AdminStore) Seed() error { - var adminNumbers []int64 + var config Config - numbersEnv := initializers.GetEnv("ADMIN_NUMBERS", "") - for _, numStr := range strings.Split(numbersEnv, ",") { - if num, err := strconv.ParseInt(strings.TrimSpace(numStr), 10, 64); err == nil { - adminNumbers = append(adminNumbers, num) - } else { - log.Printf("Skipping invalid number: %s", numStr) - } - } - file, err := os.Create(as.filePath) + store := as.fsStore + defer store.Close() + + data, err := os.ReadFile("admin_numbers.json") if err != nil { return err } - defer file.Close() - - writer := bufio.NewWriter(file) - for _, num := range adminNumbers { - _, err := writer.WriteString(strconv.FormatInt(num, 10) + "\n") + if err := json.Unmarshal(data, &config); err != nil { + return err + } + for _, admin := range config.Admins { + err := store.Put(as.ctx, []byte(admin.PhoneNumber), []byte("1")) if err != nil { + logg.Printf(logging.LVL_DEBUG, "Failed to insert admin number", admin.PhoneNumber) return err } } - return writer.Flush() + return nil } -func (as *AdminStore) load() ([]int64, error) { - file, err := os.Open(as.filePath) +// Checks if the given sessionId is listed as an admin. +func (as *AdminStore) IsAdmin(sessionId string) (bool, error) { + _, err := as.fsStore.Get(as.ctx, []byte(sessionId)) if err != nil { - return nil, err - } - defer file.Close() - - var numbers []int64 - scanner := bufio.NewScanner(file) - for scanner.Scan() { - num, err := strconv.ParseInt(scanner.Text(), 10, 64) - if err != nil { - return nil, err - } - numbers = append(numbers, num) - } - return numbers, scanner.Err() -} - -func (as *AdminStore) IsAdmin(phoneNumber int64) (bool, error) { - phoneNumbers, err := as.load() - if err != nil { - return false, err - } - for _, phonenumber := range phoneNumbers { - if phonenumber == phoneNumber { - return true, nil + if db.IsNotFound(err) { + logg.Printf(logging.LVL_INFO, "Returning false because session id was not found") + return false, nil + } else { + return false, err } } - return false, nil + + return true, nil } From c42b1cd66b9dd63b5f31ca5c60bc483d2230bee1 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:32:01 +0300 Subject: [PATCH 29/86] provide required handler functions and admin store --- internal/handlers/handlerservice.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index b4cd592..247e6c5 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -8,6 +8,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/handlers/ussd" + "git.grassecon.net/urdt/ussd/internal/utils" ) type HandlerService interface { @@ -28,6 +29,7 @@ type LocalHandlerService struct { DbRs *resource.DbResource Pe *persist.Persister UserdataStore *db.Db + AdminStore *utils.AdminStore Cfg engine.Config Rs resource.Resource } @@ -53,8 +55,12 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { ls.UserdataStore = db } +func (ls *LocalHandlerService) SetAdminStore(adminstore *utils.AdminStore) { + ls.AdminStore = adminstore +} + func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { - ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, accountService) + ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService) if err != nil { return nil, err } @@ -103,6 +109,8 @@ func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceIn ls.DbRs.AddLocalFunc("validate_blocked_number", ussdHandlers.ValidateBlockedNumber) ls.DbRs.AddLocalFunc("retrieve_blocked_number", ussdHandlers.RetrieveBlockedNumber) ls.DbRs.AddLocalFunc("reset_unregistered_number", ussdHandlers.ResetUnregisteredNumber) + ls.DbRs.AddLocalFunc("reset_others_pin", ussdHandlers.ResetOthersPin) + ls.DbRs.AddLocalFunc("save_others_temporary_pin", ussdHandlers.SaveOthersTemporaryPin) return ussdHandlers, nil } From c2068db050a931b6f6b9e75bdf876f612d072087 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:33:22 +0300 Subject: [PATCH 30/86] update handler functions --- services/registration/confirm_others_new_pin.vis | 4 ++-- services/registration/enter_others_new_pin.vis | 4 ++-- services/registration/pin_reset_result.vis | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/services/registration/confirm_others_new_pin.vis b/services/registration/confirm_others_new_pin.vis index be6734f..319346a 100644 --- a/services/registration/confirm_others_new_pin.vis +++ b/services/registration/confirm_others_new_pin.vis @@ -1,9 +1,9 @@ LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number CATCH invalid_others_pin flag_valid_pin 0 -LOAD save_temporary_pin 6 -RELOAD save_temporary_pin CATCH pin_reset_result flag_account_authorized 1 +LOAD save_others_temporary_pin 6 +RELOAD save_others_temporary_pin MOUT back 0 HALT INCMP _ 0 diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis index aa2818d..16db41c 100644 --- a/services/registration/enter_others_new_pin.vis +++ b/services/registration/enter_others_new_pin.vis @@ -2,7 +2,7 @@ LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number MOUT back 0 HALT -INCMP _ 0 -LOAD verify_new_pin 0 +LOAD verify_new_pin 6 RELOAD verify_new_pin +INCMP _ 0 INCMP * confirm_others_new_pin diff --git a/services/registration/pin_reset_result.vis b/services/registration/pin_reset_result.vis index ed71200..34b9789 100644 --- a/services/registration/pin_reset_result.vis +++ b/services/registration/pin_reset_result.vis @@ -1,5 +1,6 @@ LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number +LOAD reset_others_pin 6 MOUT back 0 MOUT quit 9 HALT From dc418771a79dbb8653fc3251554b0d1591574d4d Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:33:48 +0300 Subject: [PATCH 31/86] attach an admin store for phone numbers --- cmd/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 4d23011..7dd3cd6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -49,7 +49,7 @@ func main() { ctx = context.WithValue(ctx, "Database", database) pfp := path.Join(scriptDir, "pp.csv") - as := utils.NewAdminStore("admin_numbers.txt") + as, _ := utils.NewAdminStore(ctx, "admin_numbers") as.Seed() cfg := engine.Config{ @@ -94,6 +94,7 @@ func main() { lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdatastore) + lhs.SetAdminStore(as) lhs.SetPersister(pe) if err != nil { From 017691a40cac3bab37121d875a3da914eca8bd53 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:41:14 +0300 Subject: [PATCH 32/86] define structure for admin numbers --- admin_numbers.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 admin_numbers.json diff --git a/admin_numbers.json b/admin_numbers.json new file mode 100644 index 0000000..ca58a23 --- /dev/null +++ b/admin_numbers.json @@ -0,0 +1,7 @@ +{ + "admins": [ + { + "phonenumber" : "" + } + ] +} \ No newline at end of file From 888d3befe99437be89ade4cd60915ca3730899c4 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:50:12 +0300 Subject: [PATCH 33/86] add actual pin reset functionality --- internal/handlers/ussd/menuhandler.go | 61 ++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 70510ee..8b0c385 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -69,11 +69,12 @@ type Handlers struct { st *state.State ca cache.Memory userdataStore utils.DataStore + adminstore *utils.AdminStore flagManager *asm.FlagParser accountService server.AccountServiceInterface } -func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService server.AccountServiceInterface) (*Handlers, error) { +func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService server.AccountServiceInterface) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } @@ -83,6 +84,7 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService s h := &Handlers{ userdataStore: userDb, flagManager: appFlags, + adminstore: adminstore, accountService: accountService, } return h, nil @@ -120,9 +122,7 @@ func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource sessionId, _ := ctx.Value("SessionId").(string) flag_admin_privilege, _ := h.flagManager.GetFlag("flag_admin_privilege") - number, _ := strconv.ParseInt(sessionId, 10, 64) - as := utils.NewAdminStore("admin_numbers.txt") - isAdmin, _ := as.IsAdmin(number) + isAdmin, _ := h.adminstore.IsAdmin(sessionId) if isAdmin { r.FlagSet = append(r.FlagSet, flag_admin_privilege) @@ -220,7 +220,11 @@ func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byt return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + if err != nil { + return res, err + } + temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_PIN) if err != nil { return res, err } @@ -272,6 +276,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt } res.FlagReset = append(res.FlagReset, flag_incorrect_pin) + fmt.Println("Saving:", string(accountPIN)) store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN)) @@ -282,6 +287,29 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt return res, nil } +func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + var err error + + store := h.userdataStore + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + temporaryPin := string(input) + blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + + if err != nil { + return res, err + } + err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_PIN, []byte(temporaryPin)) + if err != nil { + return res, err + } + + return res, nil +} + func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result sessionId, ok := ctx.Value("SessionId").(string) @@ -672,7 +700,6 @@ func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []by var res resource.Result flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format") - res.FlagReset = append(res.FlagReset, flag_incorrect_date_format) return res, nil } @@ -755,6 +782,28 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input return res, nil } +func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + store := h.userdataStore + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + if err != nil { + return res, err + } + temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_PIN) + if err != nil { + return res, err + } + err = store.WriteEntry(ctx, string(blockedPhonenumber), utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + if err != nil { + return res, nil + } + return res, nil +} + func (h *Handlers) ResetUnregisteredNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") From cf523e30f89571ed58c933bbd2b0162034947cdc Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:50:31 +0300 Subject: [PATCH 34/86] update handler in test --- internal/handlers/ussd/menuhandler_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 28d25e8..d23408a 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -39,7 +39,7 @@ func TestNewHandlers(t *testing.T) { } t.Run("Valid UserDataStore", func(t *testing.T) { mockStore := &mocks.MockUserDataStore{} - handlers, err := NewHandlers(fm.parser, mockStore, &accountService) + handlers, err := NewHandlers(fm.parser, mockStore, nil, &accountService) if err != nil { t.Fatalf("expected no error, got %v", err) } @@ -55,7 +55,7 @@ func TestNewHandlers(t *testing.T) { t.Run("Nil UserDataStore", func(t *testing.T) { appFlags := &asm.FlagParser{} - handlers, err := NewHandlers(appFlags, nil, &accountService) + handlers, err := NewHandlers(appFlags, nil, nil, &accountService) if err == nil { t.Fatal("expected an error, got none") @@ -1481,8 +1481,8 @@ func TestValidateAmount(t *testing.T) { }, }, { - name: "Test with invalid amount format", - input: []byte("0.02ms"), + name: "Test with invalid amount format", + input: []byte("0.02ms"), activeBal: []byte("5"), expectedResult: resource.Result{ FlagSet: []uint32{flag_invalid_amount}, From 14648fec6cfcc348bf5e38ff6e0eb17a53cc015e Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 12:02:16 +0000 Subject: [PATCH 35/86] Edit comment --- common/user_store.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/user_store.go b/common/user_store.go index 8d982ab..4b8409f 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -16,7 +16,7 @@ type UserDataStore struct { db.Db } -// ReadEntry retrieves an entry from the store based on the provided parameters. +// ReadEntry retrieves an entry to the userdata store. func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) @@ -24,6 +24,7 @@ func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ return store.Get(ctx, k) } +// WriteEntry adds an entry to the userdata store. func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) From ff26ccc545d1b09456a1875d8e59ef290a15f349 Mon Sep 17 00:00:00 2001 From: lash Date: Wed, 30 Oct 2024 13:09:15 +0000 Subject: [PATCH 36/86] Expose api interface --- cmd/africastalking/main.go | 4 ++-- cmd/async/main.go | 4 ++-- cmd/http/main.go | 4 ++-- cmd/main.go | 4 ++-- internal/handlers/handlerservice.go | 5 +++-- internal/handlers/ussd/menuhandler.go | 6 +++--- internal/testutil/TestEngine.go | 6 +++--- internal/testutil/testtag/offlinetest.go | 4 ++-- {internal/handlers/server => remote}/accountservice.go | 2 +- 9 files changed, 20 insertions(+), 19 deletions(-) rename {internal/handlers/server => remote}/accountservice.go (99%) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 79fb091..7c98f38 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -19,9 +19,9 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" httpserver "git.grassecon.net/urdt/ussd/internal/http" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -139,7 +139,7 @@ func main() { os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/async/main.go b/cmd/async/main.go index 902dfc7..b879c68 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -16,8 +16,8 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -106,7 +106,7 @@ func main() { lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/http/main.go b/cmd/http/main.go index ece882e..638ca87 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -18,9 +18,9 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" httpserver "git.grassecon.net/urdt/ussd/internal/http" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -99,7 +99,7 @@ func main() { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/main.go b/cmd/main.go index 21ca0c3..13ceb3c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -13,8 +13,8 @@ import ( "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/initializers" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -97,7 +97,7 @@ func main() { os.Exit(1) } - accountService := server.AccountService{} + accountService := remote.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 311e694..b409fa6 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -6,8 +6,9 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/internal/handlers/ussd" + "git.grassecon.net/urdt/ussd/remote" ) type HandlerService interface { @@ -53,7 +54,7 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { ls.UserdataStore = db } -func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { +func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceInterface) (*ussd.Handlers, error) { ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore,accountService) if err != nil { return nil, err diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 303bea9..aa5c1aa 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -19,9 +19,9 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" + "git.grassecon.net/urdt/ussd/remote" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -65,10 +65,10 @@ type Handlers struct { ca cache.Memory userdataStore common.DataStore flagManager *asm.FlagParser - accountService server.AccountServiceInterface + accountService remote.AccountServiceInterface } -func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService server.AccountServiceInterface) (*Handlers, error) { +func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService remote.AccountServiceInterface) (*Handlers, error) { if userdataStore == nil { return nil, fmt.Errorf("cannot create handler with nil userdata store") } diff --git a/internal/testutil/TestEngine.go b/internal/testutil/TestEngine.go index bd6bc7f..fa585ae 100644 --- a/internal/testutil/TestEngine.go +++ b/internal/testutil/TestEngine.go @@ -11,11 +11,11 @@ import ( "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/resource" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" "git.grassecon.net/urdt/ussd/internal/testutil/testtag" testdataloader "github.com/peteole/testdata-loader" + "git.grassecon.net/urdt/ussd/remote" ) var ( @@ -83,7 +83,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { } if testtag.AccountService == nil { - testtag.AccountService = &server.AccountService{} + testtag.AccountService = &remote.AccountService{} } switch testtag.AccountService.(type) { @@ -91,7 +91,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { go func() { eventChannel <- false }() - case *server.AccountService: + case *remote.AccountService: go func() { time.Sleep(5 * time.Second) // Wait for 5 seconds eventChannel <- true diff --git a/internal/testutil/testtag/offlinetest.go b/internal/testutil/testtag/offlinetest.go index 70e2e80..831bf09 100644 --- a/internal/testutil/testtag/offlinetest.go +++ b/internal/testutil/testtag/offlinetest.go @@ -3,10 +3,10 @@ package testtag import ( - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/remote" accountservice "git.grassecon.net/urdt/ussd/internal/testutil/testservice" ) var ( - AccountService server.AccountServiceInterface = &accountservice.TestAccountService{} + AccountService remote.AccountServiceInterface = &accountservice.TestAccountService{} ) diff --git a/internal/handlers/server/accountservice.go b/remote/accountservice.go similarity index 99% rename from internal/handlers/server/accountservice.go rename to remote/accountservice.go index 890d1db..236ccf4 100644 --- a/internal/handlers/server/accountservice.go +++ b/remote/accountservice.go @@ -1,4 +1,4 @@ -package server +package remote import ( "context" From d93a26f9b0d2ae02c9798825efac879d09630cf0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 17:58:52 +0300 Subject: [PATCH 37/86] remove function exec after HALT --- services/registration/enter_other_number.vis | 3 --- 1 file changed, 3 deletions(-) diff --git a/services/registration/enter_other_number.vis b/services/registration/enter_other_number.vis index e2fa243..0957165 100644 --- a/services/registration/enter_other_number.vis +++ b/services/registration/enter_other_number.vis @@ -4,7 +4,4 @@ RELOAD reset_account_authorized MOUT back 0 HALT INCMP _ 0 -LOAD validate_blocked_number 20 -RELOAD validate_blocked_number -CATCH unregistered_number flag_unregistered_number 1 INCMP enter_others_new_pin * From 41585f831c3e38978c99d34a20859e4ab8ef6e71 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 18:00:38 +0300 Subject: [PATCH 38/86] move catch and load to next node --- services/registration/enter_others_new_pin.vis | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis index 16db41c..49c2426 100644 --- a/services/registration/enter_others_new_pin.vis +++ b/services/registration/enter_others_new_pin.vis @@ -1,3 +1,6 @@ +LOAD validate_blocked_number 20 +RELOAD validate_blocked_number +CATCH unregistered_number flag_unregistered_number 1 LOAD retrieve_blocked_number 0 MAP retrieve_blocked_number MOUT back 0 From 7c823e07ca6c4f0175e58902522f1de97a104599 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 18:01:20 +0300 Subject: [PATCH 39/86] move to root node after on back --- services/registration/unregistered_number.vis | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/registration/unregistered_number.vis b/services/registration/unregistered_number.vis index 114113f..0c66912 100644 --- a/services/registration/unregistered_number.vis +++ b/services/registration/unregistered_number.vis @@ -1,7 +1,7 @@ LOAD reset_unregistered_number 0 RELOAD reset_unregistered_number -MOUT retry 1 +MOUT back 1 MOUT quit 9 HALT -INCMP _ 1 +INCMP ^ 1 INCMP quit 9 From ea4c6d9314158ecb7a6625b9c6544285da4a7bd1 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 18:01:43 +0300 Subject: [PATCH 40/86] check for phone number validity --- internal/handlers/ussd/menuhandler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 8b0c385..4d6f724 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -816,7 +816,6 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input var err error flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number") - store := h.userdataStore sessionId, ok := ctx.Value("SessionId").(string) if !ok { @@ -825,6 +824,7 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input blockedNumber := string(input) _, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY) if !isValidPhoneNumber(blockedNumber) { + res.FlagSet = append(res.FlagSet, flag_unregistered_number) return res, nil } if err != nil { From 833d52a558b2e20359ebe4beeb482dd7e2757397 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 21:26:11 +0300 Subject: [PATCH 41/86] remove print message --- internal/handlers/ussd/menuhandler.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index bbcfd58..3ffa61b 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -19,9 +19,9 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.grassecon.net/urdt/ussd/common" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/utils" - "git.grassecon.net/urdt/ussd/common" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -283,10 +283,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagSet = append(res.FlagSet, flag_incorrect_pin) return res, nil } - res.FlagReset = append(res.FlagReset, flag_incorrect_pin) - fmt.Println("Saving:", string(accountPIN)) - store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN)) if err != nil { From 8093eae61aeb35e0a76fce275fca04fb950adedb Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 21:26:52 +0300 Subject: [PATCH 42/86] use 0 instead of 1 for back --- services/registration/unregistered_number.vis | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/registration/unregistered_number.vis b/services/registration/unregistered_number.vis index 0c66912..0ff96be 100644 --- a/services/registration/unregistered_number.vis +++ b/services/registration/unregistered_number.vis @@ -1,7 +1,7 @@ LOAD reset_unregistered_number 0 RELOAD reset_unregistered_number -MOUT back 1 +MOUT back 0 MOUT quit 9 HALT -INCMP ^ 1 +INCMP ^ 0 INCMP quit 9 From c6ca3f6be4fb405ebf0a620a26adc677242d8d8f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 22:32:38 +0300 Subject: [PATCH 43/86] fix sink error --- services/registration/confirm_others_new_pin.vis | 2 +- services/registration/enter_others_new_pin.vis | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/services/registration/confirm_others_new_pin.vis b/services/registration/confirm_others_new_pin.vis index 319346a..f63d7ae 100644 --- a/services/registration/confirm_others_new_pin.vis +++ b/services/registration/confirm_others_new_pin.vis @@ -1,4 +1,4 @@ -LOAD retrieve_blocked_number 0 +RELOAD retrieve_blocked_number MAP retrieve_blocked_number CATCH invalid_others_pin flag_valid_pin 0 CATCH pin_reset_result flag_account_authorized 1 diff --git a/services/registration/enter_others_new_pin.vis b/services/registration/enter_others_new_pin.vis index 49c2426..7711c97 100644 --- a/services/registration/enter_others_new_pin.vis +++ b/services/registration/enter_others_new_pin.vis @@ -1,7 +1,8 @@ -LOAD validate_blocked_number 20 +LOAD validate_blocked_number 6 RELOAD validate_blocked_number CATCH unregistered_number flag_unregistered_number 1 LOAD retrieve_blocked_number 0 +RELOAD retrieve_blocked_number MAP retrieve_blocked_number MOUT back 0 HALT From d4341940218dc1b24795ccdb10165fc3098242a0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 23:21:15 +0300 Subject: [PATCH 44/86] catch incorrect pin entry --- services/registration/confirm_others_new_pin.vis | 1 + 1 file changed, 1 insertion(+) diff --git a/services/registration/confirm_others_new_pin.vis b/services/registration/confirm_others_new_pin.vis index f63d7ae..9132dc4 100644 --- a/services/registration/confirm_others_new_pin.vis +++ b/services/registration/confirm_others_new_pin.vis @@ -1,3 +1,4 @@ +CATCH pin_entry flag_incorrect_pin 1 RELOAD retrieve_blocked_number MAP retrieve_blocked_number CATCH invalid_others_pin flag_valid_pin 0 From 1e638238ed368319fb84ed9deb8d90d0df55b28d Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 01:28:37 +0000 Subject: [PATCH 45/86] WIP refactor models usage --- config/config.go | 67 ++++++-- internal/handlers/ussd/menuhandler.go | 20 +-- internal/handlers/ussd/menuhandler_test.go | 1 - internal/models/accountresponse.go | 10 +- internal/models/balanceresponse.go | 17 +- internal/models/trackstatusresponse.go | 23 ++- internal/models/vouchersresponse.go | 13 -- internal/testutil/mocks/servicemock.go | 27 ++-- .../testservice/TestAccountService.go | 78 +++------ remote/accountservice.go | 149 ++++++++++++------ 10 files changed, 229 insertions(+), 176 deletions(-) diff --git a/config/config.go b/config/config.go index 43466c3..a5c89a7 100644 --- a/config/config.go +++ b/config/config.go @@ -1,18 +1,67 @@ package config -import "git.grassecon.net/urdt/ussd/initializers" +import ( + "net/url" + + "git.grassecon.net/urdt/ussd/initializers" +) + +const ( + createAccountPath = "/api/v2/account/create" + trackStatusPath = "/api/track" + balancePathPrefix = "/api/account" + trackPath = "/api/v2/account/status" + voucherHoldingsPathPrefix = "/api/v1/holdings" + voucherTransfersPathPrefix = "/api/v1/transfers/last10" +) + +var ( + custodialURLBase string + dataURLBase string + CustodialAPIKey string + DataAPIKey string +) var ( CreateAccountURL string TrackStatusURL string - BalanceURL string - TrackURL string + BalanceURL string + TrackURL string + VoucherHoldingsURL string + VoucherTransfersURL string ) -// LoadConfig initializes the configuration values after environment variables are loaded. -func LoadConfig() { - CreateAccountURL = initializers.GetEnv("CREATE_ACCOUNT_URL", "http://localhost:5003/api/v2/account/create") - TrackStatusURL = initializers.GetEnv("TRACK_STATUS_URL", "https://custodial.sarafu.africa/api/track/") - BalanceURL = initializers.GetEnv("BALANCE_URL", "https://custodial.sarafu.africa/api/account/status/") - TrackURL = initializers.GetEnv("TRACK_URL", "http://localhost:5003/api/v2/account/status") +func setBase() error { + var err error + + custodialURLBase = initializers.GetEnv("CUSTODIAL_URL_BASE", "http://localhost:5003") + dataURLBase = initializers.GetEnv("DATA_URL_BASE", "http://localhost:5006") + CustodialAPIKey = initializers.GetEnv("CUSTODIAL_API_KEY", "xd") + DataAPIKey = initializers.GetEnv("DATA_API_KEY", "xd") + + _, err = url.JoinPath(custodialURLBase, "/foo") + if err != nil { + return err + } + _, err = url.JoinPath(dataURLBase, "/bar") + if err != nil { + return err + } + return nil +} + +// LoadConfig initializes the configuration values after environment variables are loaded. +func LoadConfig() error { + err := setBase() + if err != nil { + return err + } + CreateAccountURL, _ = url.JoinPath(custodialURLBase, createAccountPath) + TrackStatusURL, _ = url.JoinPath(custodialURLBase, trackStatusPath) + BalanceURL, _ = url.JoinPath(custodialURLBase, balancePathPrefix) + TrackURL, _ = url.JoinPath(custodialURLBase, trackPath) + VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) + VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) + + return nil } diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f568e6a..5f6f81a 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -149,12 +149,12 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") - okResponse, err := h.accountService.CreateAccount(ctx) + r, err := h.accountService.CreateAccount(ctx) if err != nil { return err } - trackingId := okResponse.Result["trackingId"].(string) - publicKey := okResponse.Result["publicKey"].(string) + trackingId := r.TrackingId + publicKey := r.PublicKey data := map[common.DataTyp]string{ common.DATA_TRACKING_ID: trackingId, @@ -682,6 +682,7 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) ( func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result + flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") sessionId, ok := ctx.Value("SessionId").(string) @@ -699,14 +700,13 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input balanceResponse, err := h.accountService.CheckBalance(ctx, string(publicKey)) if err != nil { - return res, nil - } - if !balanceResponse.Ok { res.FlagSet = append(res.FlagSet, flag_api_error) return res, nil } res.FlagReset = append(res.FlagReset, flag_api_error) - balance := balanceResponse.Result.Balance + + //balance := balanceResponse.Result.Balance + balance := balanceResponse.Balance switch balanceType { case "my": @@ -1066,13 +1066,13 @@ func (h *Handlers) SetDefaultVoucher(ctx context.Context, sym string, input []by } // Return if there is no voucher - if len(vouchersResp.Result.Holdings) == 0 { + if len(vouchersResp) == 0 { res.FlagSet = append(res.FlagSet, flag_no_active_voucher) return res, nil } // Use only the first voucher - firstVoucher := vouchersResp.Result.Holdings[0] + firstVoucher := vouchersResp[0] defaultSym := firstVoucher.TokenSymbol defaultBal := firstVoucher.Balance @@ -1119,7 +1119,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) return res, nil } - data := utils.ProcessVouchers(vouchersResp.Result.Holdings) + data := utils.ProcessVouchers(vouchersResp) // Store all voucher data dataMap := map[string]string{ diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index bae95a8..5f3c953 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1159,7 +1159,6 @@ func TestCheckAccountStatus(t *testing.T) { // Assert that expectations were met mockDataStore.AssertExpectations(t) - }) } diff --git a/internal/models/accountresponse.go b/internal/models/accountresponse.go index efcc30b..278e0e9 100644 --- a/internal/models/accountresponse.go +++ b/internal/models/accountresponse.go @@ -1,10 +1,6 @@ package models -type AccountResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` // Include the description field - Result struct { - PublicKey string `json:"publicKey"` - TrackingId string `json:"trackingId"` - } `json:"result"` +type AccountResult struct { + PublicKey string `json:"publicKey"` + TrackingId string `json:"trackingId"` } diff --git a/internal/models/balanceresponse.go b/internal/models/balanceresponse.go index 57c8e5a..3d57c95 100644 --- a/internal/models/balanceresponse.go +++ b/internal/models/balanceresponse.go @@ -3,10 +3,15 @@ package models import "encoding/json" -type BalanceResponse struct { - Ok bool `json:"ok"` - Result struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - } `json:"result"` +//type BalanceResponse struct { +// Ok bool `json:"ok"` +// Result struct { +// Balance string `json:"balance"` +// Nonce json.Number `json:"nonce"` +// } `json:"result"` +//} +// +type BalanceResult struct { + Balance string `json:"balance"` + Nonce json.Number `json:"nonce"` } diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 6b96d90..6130c6e 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -4,23 +4,18 @@ import ( "encoding/json" "time" ) -type Transaction struct { +//type Transaction struct { +// CreatedAt time.Time `json:"createdAt"` +// Status string `json:"status"` +// TransferValue json.Number `json:"transferValue"` +// TxHash string `json:"txHash"` +// TxType string `json:"txType"` +//} + +type TrackStatusResult struct { CreatedAt time.Time `json:"createdAt"` Status string `json:"status"` TransferValue json.Number `json:"transferValue"` TxHash string `json:"txHash"` TxType string `json:"txType"` } - -type TrackStatusResponse struct { - Ok bool `json:"ok"` - Result struct { - Transaction struct { - CreatedAt time.Time `json:"createdAt"` - Status string `json:"status"` - TransferValue json.Number `json:"transferValue"` - TxHash string `json:"txHash"` - TxType string `json:"txType"` - } - } `json:"result"` -} diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go index 09b085d..2640e7f 100644 --- a/internal/models/vouchersresponse.go +++ b/internal/models/vouchersresponse.go @@ -1,14 +1 @@ package models - -import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" - -type VoucherHoldingResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` - Result VoucherResult `json:"result"` -} - -// VoucherResult holds the list of token holdings -type VoucherResult struct { - Holdings []dataserviceapi.TokenHoldings `json:"holdings"` -} diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index de0e99a..3b36ba7 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -5,6 +5,7 @@ import ( "git.grassecon.net/urdt/ussd/internal/models" "github.com/grassrootseconomics/eth-custodial/pkg/api" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) @@ -13,28 +14,28 @@ type MockAccountService struct { mock.Mock } -func (m *MockAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { +func (m *MockAccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { args := m.Called() - return args.Get(0).(*api.OKResponse), args.Error(1) + return args.Get(0).(*models.AccountResult), args.Error(1) } -func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { +func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { args := m.Called(publicKey) - return args.Get(0).(*models.BalanceResponse), args.Error(1) + return args.Get(0).(*models.BalanceResult), args.Error(1) } -func (m *MockAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { +func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*api.OKResponse, error) { args := m.Called(trackingId) - return args.Get(0).(*models.TrackStatusResponse), args.Error(1) -} - -func (m *MockAccountService) TrackAccountStatus(ctx context.Context,publicKey string) (*api.OKResponse, error) { - args := m.Called(publicKey) return args.Get(0).(*api.OKResponse), args.Error(1) } - -func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { +func (m *MockAccountService) CheckAccountStatus(ctx context.Context,publicKey string) (*models.TrackStatusResult, error) { args := m.Called(publicKey) - return args.Get(0).(*models.VoucherHoldingResponse), args.Error(1) + return args.Get(0).(*models.TrackStatusResult), args.Error(1) +} + + +func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + args := m.Called(publicKey) + return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 745b80d..885e63f 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -13,54 +13,29 @@ import ( type TestAccountService struct { } -func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "trackingId": "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d", - "publicKey": "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD", - }, +func (tas *TestAccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { + return &models.AccountResult { + TrackingId: "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d", + PublicKey: "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD", }, nil } -func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { - balanceResponse := &models.BalanceResponse{ - Ok: true, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, +func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { + balanceResponse := &models.BalanceResult { + Balance: "0.003 CELO", + Nonce: json.Number("0"), } - return balanceResponse, nil } -func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { - trackResponse := &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - } - return trackResponse, nil +func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { + return &models.TrackStatusResult { + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", + }, nil } func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { @@ -73,18 +48,13 @@ func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey }, nil } -func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { - return &models.VoucherHoldingResponse{ - Ok: true, - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", - TokenSymbol: "SRF", - TokenDecimals: "6", - Balance: "2745987", - }, - }, +func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + return []dataserviceapi.TokenHoldings { + dataserviceapi.TokenHoldings { + ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", + TokenSymbol: "SRF", + TokenDecimals: "6", + Balance: "2745987", }, - }, nil + }, nil } diff --git a/remote/accountservice.go b/remote/accountservice.go index 236ccf4..c11910f 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -4,27 +4,29 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" - "os" + "net/url" + dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" + "github.com/grassrootseconomics/eth-custodial/pkg/api" "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" ) var ( - okResponse api.OKResponse - errResponse api.ErrResponse ) type AccountServiceInterface interface { - CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) - CreateAccount(ctx context.Context) (*api.OKResponse, error) - CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) + //CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) + CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) + CreateAccount(ctx context.Context) (*models.AccountResult, error) + //CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) + // TODO: poorly named method seems to be checking transaction + CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) - FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) + FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + //FetchVouchers(ctx context.Context, publicKey string) (*api.OKResponse, error) } type AccountService struct { @@ -39,32 +41,38 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { - resp, err := http.Get(config.BalanceURL + trackingId) - if err != nil { - return nil, err - } - defer resp.Body.Close() +func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { + var r models.TrackStatusResult - body, err := io.ReadAll(resp.Body) + ep, err := url.JoinPath(config.TrackURL, trackingId) if err != nil { return nil, err } - var trackResp models.TrackStatusResponse - err = json.Unmarshal(body, &trackResp) + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } - return &trackResp, nil + _, err = doCustodialRequest(ctx, req, &r) + if err != nil { + return nil, err + } + + return &r, nil } func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { + var okResponse api.OKResponse + var errResponse api.ErrResponse var err error - // Construct the URL with the path parameter - url := fmt.Sprintf("%s/%s", config.TrackURL, publicKey) - req, err := http.NewRequest("GET", url, nil) + + ep, err := url.JoinPath(config.TrackURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } @@ -104,41 +112,83 @@ func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey stri // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint. // Parameters: // - publicKey: The public key associated with the account whose balance needs to be checked. -func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { - resp, err := http.Get(config.BalanceURL + publicKey) +func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { + var balanceResult models.BalanceResult + + ep, err := url.JoinPath(config.BalanceURL, publicKey) if err != nil { return nil, err } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } - var balanceResp models.BalanceResponse - err = json.Unmarshal(body, &balanceResp) - if err != nil { - return nil, err - } - return &balanceResp, nil + + _, err = doCustodialRequest(ctx, req, &balanceResult) + return &balanceResult, err } + // CreateAccount creates a new account in the custodial system. // Returns: // - *models.AccountResponse: A pointer to an AccountResponse struct containing the details of the created account. // If there is an error during the request or processing, this will be nil. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil. -func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { - var err error - +func (as *AccountService) CreateAccount(ctx context.Context) (*models.AccountResult, error) { + var r models.AccountResult // Create a new request req, err := http.NewRequest("POST", config.CreateAccountURL, nil) if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-GE-KEY", "xd") + _, err = doCustodialRequest(ctx, req, &r) + if err != nil { + return nil, err + } + + return &r, nil +} + +// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint +// Parameters: +// - publicKey: The public key associated with the account. +func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { + var r []dataserviceapi.TokenHoldings + + req, err := http.NewRequest("GET", config.VoucherHoldingsURL, nil) + if err != nil { + return nil, err + } + + _, err = doDataRequest(ctx, req, r) + if err != nil { + return nil, err + } + + return r, nil + +// +// file, err := os.Open("sample_tokens.json") +// if err != nil { +// return nil, err +// } +// defer file.Close() +// var holdings models.VoucherHoldingResponse +// +// if err := json.NewDecoder(file).Decode(&holdings); err != nil { +// return nil, err +// } +// return &holdings, nil +} + +func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + var okResponse api.OKResponse + var errResponse api.ErrResponse + + req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { errResponse.Description = err.Error() @@ -165,21 +215,22 @@ func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, e return nil, errors.New("Empty api result") } return &okResponse, nil -} -// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint -// Parameters: -// - publicKey: The public key associated with the account. -func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { - file, err := os.Open("sample_tokens.json") + v, err := json.Marshal(okResponse.Result) if err != nil { return nil, err } - defer file.Close() - var holdings models.VoucherHoldingResponse - if err := json.NewDecoder(file).Decode(&holdings); err != nil { - return nil, err - } - return &holdings, nil + err = json.Unmarshal(v, &rcpt) + return &okResponse, err +} + +func doCustodialRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + req.Header.Set("X-GE-KEY", config.CustodialAPIKey) + return doRequest(ctx, req, rcpt) +} + +func doDataRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { + req.Header.Set("X-GE-KEY", config.DataAPIKey) + return doRequest(ctx, req, rcpt) } From a48170321c03aa232aabf7065f98c08c947e6e9f Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 01:51:36 +0000 Subject: [PATCH 46/86] Finish refactor result models --- internal/handlers/ussd/menuhandler_test.go | 136 ++++++--------------- 1 file changed, 36 insertions(+), 100 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 5f3c953..77447ca 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -88,18 +88,14 @@ func TestCreateAccount(t *testing.T) { tests := []struct { name string - serverResponse *api.OKResponse + serverResponse *models.AccountResult expectedResult resource.Result }{ { name: "Test account creation success", - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation successed", - Result: map[string]any{ - "trackingId": "1234567890", - "publicKey": "0xD3adB33f", - }, + serverResponse: &models.AccountResult{ + TrackingId: "1234567890", + PublicKey: "0xD3adB33f", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_created}, @@ -119,9 +115,9 @@ func TestCreateAccount(t *testing.T) { flagManager: fm.parser, } - publicKey := tt.serverResponse.Result["publicKey"].(string) + publicKey := tt.serverResponse.PublicKey data := map[common.DataTyp]string{ - common.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), + common.DATA_TRACKING_ID: tt.serverResponse.TrackingId, common.DATA_PUBLIC_KEY: publicKey, } @@ -1055,7 +1051,7 @@ func TestCheckAccountStatus(t *testing.T) { name string input []byte serverResponse *api.OKResponse - response *models.TrackStatusResponse + response *models.TrackStatusResult expectedResult resource.Result }{ { @@ -1068,25 +1064,12 @@ func TestCheckAccountStatus(t *testing.T) { "active": true, }, }, - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, + response: &models.TrackStatusResult { + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, @@ -1096,25 +1079,12 @@ func TestCheckAccountStatus(t *testing.T) { { name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, + response: &models.TrackStatusResult{ + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", }, serverResponse: &api.OKResponse{ Ok: true, @@ -1140,7 +1110,7 @@ func TestCheckAccountStatus(t *testing.T) { flagManager: fm.parser, } - status := tt.response.Result.Transaction.Status + status := tt.response.Status // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) @@ -1833,36 +1803,14 @@ func TestFetchCustodialBalances(t *testing.T) { tests := []struct { name string - balanceResonse *models.BalanceResponse + balanceResponse *models.BalanceResult expectedResult resource.Result }{ { name: "Test when fetch custodial balances is not a success", - balanceResonse: &models.BalanceResponse{ - Ok: false, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_api_error}, - }, - }, - { - name: "Test when fetch custodial balances is a success", - balanceResonse: &models.BalanceResponse{ - Ok: true, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, + balanceResponse: &models.BalanceResult{ + Balance: "0.003 CELO", + Nonce: json.Number("0"), }, expectedResult: resource.Result{ FlagReset: []uint32{flag_api_error}, @@ -1886,7 +1834,7 @@ func TestFetchCustodialBalances(t *testing.T) { // Set up the expected behavior of the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) + mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResponse, nil) // Call the method res, _ := h.FetchCustodialBalances(ctx, "fetch_custodial_balances", []byte("")) @@ -1918,35 +1866,24 @@ func TestSetDefaultVoucher(t *testing.T) { tests := []struct { name string - vouchersResp *models.VoucherHoldingResponse + vouchersResp []dataserviceapi.TokenHoldings expectedResult resource.Result }{ { name: "Test set default voucher when no active voucher exists", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "Vouchers fetched successfully", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{ - { - ContractAddress: "0x123", - TokenSymbol: "TOKEN1", - TokenDecimals: "18", - Balance: "100", - }, - }, + vouchersResp: []dataserviceapi.TokenHoldings { + dataserviceapi.TokenHoldings{ + ContractAddress: "0x123", + TokenSymbol: "TOKEN1", + TokenDecimals: "18", + Balance: "100", }, }, expectedResult: resource.Result{}, }, { name: "Test no vouchers available", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "No vouchers available", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{}, - }, + vouchersResp: []dataserviceapi.TokenHoldings { }, expectedResult: resource.Result{ FlagSet: []uint32{flag_no_active_voucher}, @@ -1970,8 +1907,8 @@ func TestSetDefaultVoucher(t *testing.T) { mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) - if len(tt.vouchersResp.Result.Holdings) > 0 { - firstVoucher := tt.vouchersResp.Result.Holdings[0] + if len(tt.vouchersResp) > 0 { + firstVoucher := tt.vouchersResp[0] mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_SYM, []byte(firstVoucher.TokenSymbol)).Return(nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACTIVE_BAL, []byte(firstVoucher.Balance)).Return(nil) } @@ -2006,8 +1943,7 @@ func TestCheckVouchers(t *testing.T) { mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockVouchersResponse := &models.VoucherHoldingResponse{} - mockVouchersResponse.Result.Holdings = []dataserviceapi.TokenHoldings{ + mockVouchersResponse := []dataserviceapi.TokenHoldings{ {ContractAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100"}, {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } From dc198215b1272f5f745babe3e3319295572fac3c Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 02:03:29 +0000 Subject: [PATCH 47/86] Remove commented code --- internal/handlers/ussd/menuhandler.go | 1 - internal/handlers/ussd/menuhandler_test.go | 1 - internal/models/balanceresponse.go | 8 -------- internal/models/trackstatusresponse.go | 7 ------- internal/models/vouchersresponse.go | 1 - remote/accountservice.go | 16 ---------------- 6 files changed, 34 deletions(-) delete mode 100644 internal/models/vouchersresponse.go diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 5f6f81a..98a633c 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -705,7 +705,6 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input } res.FlagReset = append(res.FlagReset, flag_api_error) - //balance := balanceResponse.Result.Balance balance := balanceResponse.Balance switch balanceType { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 77447ca..8708145 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -815,7 +815,6 @@ func TestAuthorize(t *testing.T) { // Create required mocks mockDataStore := new(mocks.MockUserDataStore) mockCreateAccountService := new(mocks.MockAccountService) - //expectedResult := resource.Result{} mockState := state.NewState(16) flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin") flag_account_authorized, _ := fm.GetFlag("flag_account_authorized") diff --git a/internal/models/balanceresponse.go b/internal/models/balanceresponse.go index 3d57c95..b2baa41 100644 --- a/internal/models/balanceresponse.go +++ b/internal/models/balanceresponse.go @@ -3,14 +3,6 @@ package models import "encoding/json" -//type BalanceResponse struct { -// Ok bool `json:"ok"` -// Result struct { -// Balance string `json:"balance"` -// Nonce json.Number `json:"nonce"` -// } `json:"result"` -//} -// type BalanceResult struct { Balance string `json:"balance"` Nonce json.Number `json:"nonce"` diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 6130c6e..202b69b 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -4,13 +4,6 @@ import ( "encoding/json" "time" ) -//type Transaction struct { -// CreatedAt time.Time `json:"createdAt"` -// Status string `json:"status"` -// TransferValue json.Number `json:"transferValue"` -// TxHash string `json:"txHash"` -// TxType string `json:"txType"` -//} type TrackStatusResult struct { CreatedAt time.Time `json:"createdAt"` diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go deleted file mode 100644 index 2640e7f..0000000 --- a/internal/models/vouchersresponse.go +++ /dev/null @@ -1 +0,0 @@ -package models diff --git a/remote/accountservice.go b/remote/accountservice.go index c11910f..bc98cf1 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -18,15 +18,12 @@ var ( ) type AccountServiceInterface interface { - //CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) CreateAccount(ctx context.Context) (*models.AccountResult, error) - //CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) // TODO: poorly named method seems to be checking transaction CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) - //FetchVouchers(ctx context.Context, publicKey string) (*api.OKResponse, error) } type AccountService struct { @@ -169,19 +166,6 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ( } return r, nil - -// -// file, err := os.Open("sample_tokens.json") -// if err != nil { -// return nil, err -// } -// defer file.Close() -// var holdings models.VoucherHoldingResponse -// -// if err := json.NewDecoder(file).Decode(&holdings); err != nil { -// return nil, err -// } -// return &holdings, nil } func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { From c4078c528005012a6f3053ff55a6e7cbbc108c0b Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 09:21:46 +0300 Subject: [PATCH 48/86] remove extra spaces --- services/registration/confirm_others_new_pin | 2 +- services/registration/pin_reset_success.vis | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/services/registration/confirm_others_new_pin b/services/registration/confirm_others_new_pin index 46c3275..d345a0a 100644 --- a/services/registration/confirm_others_new_pin +++ b/services/registration/confirm_others_new_pin @@ -1 +1 @@ -Please confirm new PIN for: {{.retrieve_blocked_number}} \ No newline at end of file +Please confirm new PIN for:{{.retrieve_blocked_number}} \ No newline at end of file diff --git a/services/registration/pin_reset_success.vis b/services/registration/pin_reset_success.vis index c942519..96dee73 100644 --- a/services/registration/pin_reset_success.vis +++ b/services/registration/pin_reset_success.vis @@ -6,5 +6,3 @@ MOUT quit 9 HALT INCMP main 0 INCMP quit 9 - - From 767a3cd64c700b59c1a54b42c57df7c0a1dd6c2b Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 09:38:51 +0300 Subject: [PATCH 49/86] remove pin guard menu option --- services/registration/guard_pin_menu | 1 - services/registration/guard_pin_menu_swa | 1 - 2 files changed, 2 deletions(-) delete mode 100644 services/registration/guard_pin_menu delete mode 100644 services/registration/guard_pin_menu_swa diff --git a/services/registration/guard_pin_menu b/services/registration/guard_pin_menu deleted file mode 100644 index 9de0ba0..0000000 --- a/services/registration/guard_pin_menu +++ /dev/null @@ -1 +0,0 @@ -Guard my PIN \ No newline at end of file diff --git a/services/registration/guard_pin_menu_swa b/services/registration/guard_pin_menu_swa deleted file mode 100644 index c6b126f..0000000 --- a/services/registration/guard_pin_menu_swa +++ /dev/null @@ -1 +0,0 @@ -Linda PIN yangu \ No newline at end of file From bab3f673ebb028d4ad2c174aa7f86a6721b80067 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 31 Oct 2024 14:13:21 +0300 Subject: [PATCH 50/86] Removed unused model --- internal/models/tokenresponse.go | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 internal/models/tokenresponse.go diff --git a/internal/models/tokenresponse.go b/internal/models/tokenresponse.go deleted file mode 100644 index d243d93..0000000 --- a/internal/models/tokenresponse.go +++ /dev/null @@ -1,18 +0,0 @@ -package models - -type ApiResponse struct { - OK bool `json:"ok"` - Description string `json:"description"` - Result Result `json:"result"` -} - -type Result struct { - Holdings []Holding `json:"holdings"` -} - -type Holding struct { - ContractAddress string `json:"contractAddress"` - TokenSymbol string `json:"tokenSymbol"` - TokenDecimals string `json:"tokenDecimals"` - Balance string `json:"balance"` -} From b9c56b04ce3f1eee05cfcc20a55eb38ee769a4ab Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 11:43:27 +0000 Subject: [PATCH 51/86] Remove obsolete track account status code --- internal/handlers/ussd/menuhandler_test.go | 17 ++++------------- internal/models/trackstatusresponse.go | 6 +++++- .../testutil/testservice/TestAccountService.go | 7 +------ 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 8708145..8c3867a 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -7,7 +7,6 @@ import ( "log" "path" "testing" - "time" "git.defalsify.org/vise.git/asm" "git.defalsify.org/vise.git/db" @@ -1064,11 +1063,7 @@ func TestCheckAccountStatus(t *testing.T) { }, }, response: &models.TrackStatusResult { - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: true, }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, @@ -1079,11 +1074,7 @@ func TestCheckAccountStatus(t *testing.T) { name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), response: &models.TrackStatusResult{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: false, }, serverResponse: &api.OKResponse{ Ok: true, @@ -1109,13 +1100,13 @@ func TestCheckAccountStatus(t *testing.T) { flagManager: fm.parser, } - status := tt.response.Status + status := tt.response.Active // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() // Call the method under test res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) diff --git a/internal/models/trackstatusresponse.go b/internal/models/trackstatusresponse.go index 202b69b..47d757d 100644 --- a/internal/models/trackstatusresponse.go +++ b/internal/models/trackstatusresponse.go @@ -5,10 +5,14 @@ import ( "time" ) -type TrackStatusResult struct { +type Transaction struct { CreatedAt time.Time `json:"createdAt"` Status string `json:"status"` TransferValue json.Number `json:"transferValue"` TxHash string `json:"txHash"` TxType string `json:"txType"` } + +type TrackStatusResult struct { + Active bool `json:"active"` +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 885e63f..78a2798 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -3,7 +3,6 @@ package testservice import ( "context" "encoding/json" - "time" "git.grassecon.net/urdt/ussd/internal/models" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -30,11 +29,7 @@ func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey strin func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { return &models.TrackStatusResult { - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", + Active: true, }, nil } From b2d180e8ebc0d353a6939d78e8f965fa6b405b89 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 12:15:07 +0000 Subject: [PATCH 52/86] WIP Trying to clean up account status check --- internal/handlers/ussd/menuhandler.go | 5 +- internal/handlers/ussd/menuhandler_test.go | 35 +++--------- internal/testutil/mocks/servicemock.go | 8 +-- .../testservice/TestAccountService.go | 13 +---- remote/accountservice.go | 55 +------------------ 5 files changed, 15 insertions(+), 101 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 98a633c..ed5f466 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -557,17 +557,16 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b if err != nil { return res, err } - okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey)) + r, err := h.accountService.TrackAccountStatus(ctx, string(publicKey)) if err != nil { res.FlagSet = append(res.FlagSet, flag_api_error) return res, err } res.FlagReset = append(res.FlagReset, flag_api_error) - isActive := okResponse.Result["active"].(bool) if !ok { return res, err } - if isActive { + if r.Active { res.FlagSet = append(res.FlagSet, flag_account_success) res.FlagReset = append(res.FlagReset, flag_account_pending) } else { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 8c3867a..7940704 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -1053,36 +1053,18 @@ func TestCheckAccountStatus(t *testing.T) { expectedResult resource.Result }{ { - name: "Test when account is on the Sarafu network", - input: []byte("TrackingId1234"), - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": true, - }, - }, - response: &models.TrackStatusResult { - Active: true, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_account_success}, - FlagReset: []uint32{flag_api_error, flag_account_pending}, - }, - }, - { - name: "Test when the account is not yet on the sarafu network", + name: "Test when the account is not yet on the sarafu network", input: []byte("TrackingId1234"), response: &models.TrackStatusResult{ Active: false, }, - serverResponse: &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": false, - }, - }, +// serverResponse: &api.OKResponse{ +// Ok: true, +// Description: "Account creation succeeded", +// Result: map[string]any{ +// "active": false, +// }, +// }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_pending}, FlagReset: []uint32{flag_api_error, flag_account_success}, @@ -1104,7 +1086,6 @@ func TestCheckAccountStatus(t *testing.T) { // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) - mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index 3b36ba7..bec48fd 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -4,7 +4,6 @@ import ( "context" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) @@ -24,13 +23,8 @@ func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) return args.Get(0).(*models.BalanceResult), args.Error(1) } -func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*api.OKResponse, error) { +func (m *MockAccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { args := m.Called(trackingId) - return args.Get(0).(*api.OKResponse), args.Error(1) -} - -func (m *MockAccountService) CheckAccountStatus(ctx context.Context,publicKey string) (*models.TrackStatusResult, error) { - args := m.Called(publicKey) return args.Get(0).(*models.TrackStatusResult), args.Error(1) } diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 78a2798..a9a3085 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -5,7 +5,6 @@ import ( "encoding/json" "git.grassecon.net/urdt/ussd/internal/models" - "github.com/grassrootseconomics/eth-custodial/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -27,22 +26,12 @@ func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey strin return balanceResponse, nil } -func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) { return &models.TrackStatusResult { Active: true, }, nil } -func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": true, - }, - }, nil -} - func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { return []dataserviceapi.TokenHoldings { dataserviceapi.TokenHoldings { diff --git a/remote/accountservice.go b/remote/accountservice.go index bc98cf1..24a469e 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -20,9 +20,7 @@ var ( type AccountServiceInterface interface { CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) CreateAccount(ctx context.Context) (*models.AccountResult, error) - // TODO: poorly named method seems to be checking transaction - CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) - TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) + TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) } @@ -38,7 +36,7 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (as *AccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { var r models.TrackStatusResult ep, err := url.JoinPath(config.TrackURL, trackingId) @@ -59,60 +57,13 @@ func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId str return &r, nil } -func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { - var okResponse api.OKResponse - var errResponse api.ErrResponse - var err error - - ep, err := url.JoinPath(config.TrackURL, publicKey) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", ep, nil) - if err != nil { - return nil, err - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-GE-KEY", "xd") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - errResponse.Description = err.Error() - return nil, err - } - if resp.StatusCode >= http.StatusBadRequest { - err := json.Unmarshal([]byte(body), &errResponse) - if err != nil { - return nil, err - } - return nil, errors.New(errResponse.Description) - } - err = json.Unmarshal([]byte(body), &okResponse) - if err != nil { - return nil, err - } - if len(okResponse.Result) == 0 { - return nil, errors.New("Empty api result") - } - return &okResponse, nil - -} - // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint. // Parameters: // - publicKey: The public key associated with the account whose balance needs to be checked. func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResult, error) { var balanceResult models.BalanceResult - ep, err := url.JoinPath(config.BalanceURL, publicKey) + ep, err := url.JoinPath(config.BalanceURL, publicKey) if err != nil { return nil, err } From 3ae75b27a5cfa10726f2dcf3b2a7afe5a7807cfe Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 12:38:31 +0000 Subject: [PATCH 53/86] WIP replaced check account method but traversal crashes --- internal/handlers/ussd/menuhandler_test.go | 7 ++++--- remote/accountservice.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 7940704..6105657 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -20,7 +20,7 @@ import ( "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" - "github.com/grassrootseconomics/eth-custodial/pkg/api" +// "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" "github.com/stretchr/testify/require" @@ -1048,7 +1048,7 @@ func TestCheckAccountStatus(t *testing.T) { tests := []struct { name string input []byte - serverResponse *api.OKResponse + //serverResponse *api.OKResponse response *models.TrackStatusResult expectedResult resource.Result }{ @@ -1086,7 +1086,8 @@ func TestCheckAccountStatus(t *testing.T) { // Define expected interactions with the mock mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_PUBLIC_KEY).Return(tt.input, nil) - mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) + //mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) + mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.response, nil) mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_STATUS, status).Return(nil).Maybe() // Call the method under test diff --git a/remote/accountservice.go b/remote/accountservice.go index 24a469e..bc6a448 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -36,10 +36,10 @@ type AccountService struct { // - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string. // - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data. // If no error occurs, this will be nil -func (as *AccountService) TrackAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResult, error) { +func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) { var r models.TrackStatusResult - ep, err := url.JoinPath(config.TrackURL, trackingId) + ep, err := url.JoinPath(config.TrackURL, publicKey) if err != nil { return nil, err } From 4bf56c525f5b0e9ac90e2c22fc68805327d03108 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 31 Oct 2024 13:19:44 +0000 Subject: [PATCH 54/86] Export voucher related code --- {internal/utils => common}/vouchers.go | 45 ++++++++++----------- {internal/utils => common}/vouchers_test.go | 2 +- internal/handlers/ussd/menuhandler.go | 10 ++--- 3 files changed, 28 insertions(+), 29 deletions(-) rename {internal/utils => common}/vouchers.go (74%) rename {internal/utils => common}/vouchers_test.go (99%) diff --git a/internal/utils/vouchers.go b/common/vouchers.go similarity index 74% rename from internal/utils/vouchers.go rename to common/vouchers.go index 0372700..291f28d 100644 --- a/internal/utils/vouchers.go +++ b/common/vouchers.go @@ -1,4 +1,4 @@ -package utils +package common import ( "context" @@ -6,7 +6,6 @@ import ( "strings" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/common" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -96,13 +95,13 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, return } -// StoreTemporaryVoucher saves voucher metadata as temporary entries in the common.DataStore. -func StoreTemporaryVoucher(ctx context.Context, store common.DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - entries := map[common.DataTyp][]byte{ - common.DATA_TEMPORARY_SYM: []byte(data.TokenSymbol), - common.DATA_TEMPORARY_BAL: []byte(data.Balance), - common.DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals), - common.DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress), +// StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore. +func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + entries := map[DataTyp][]byte{ + DATA_TEMPORARY_SYM: []byte(data.TokenSymbol), + DATA_TEMPORARY_BAL: []byte(data.Balance), + DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals), + DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress), } for key, value := range entries { @@ -113,13 +112,13 @@ func StoreTemporaryVoucher(ctx context.Context, store common.DataStore, sessionI return nil } -// GetTemporaryVoucherData retrieves temporary voucher metadata from the common.DataStore. -func GetTemporaryVoucherData(ctx context.Context, store common.DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { - keys := []common.DataTyp{ - common.DATA_TEMPORARY_SYM, - common.DATA_TEMPORARY_BAL, - common.DATA_TEMPORARY_DECIMAL, - common.DATA_TEMPORARY_ADDRESS, +// GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore. +func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { + keys := []DataTyp{ + DATA_TEMPORARY_SYM, + DATA_TEMPORARY_BAL, + DATA_TEMPORARY_DECIMAL, + DATA_TEMPORARY_ADDRESS, } data := &dataserviceapi.TokenHoldings{} @@ -141,14 +140,14 @@ func GetTemporaryVoucherData(ctx context.Context, store common.DataStore, sessio return data, nil } -// UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the common.DataStore. -func UpdateVoucherData(ctx context.Context, store common.DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { +// UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the DataStore. +func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { // Active voucher data entries - activeEntries := map[common.DataTyp][]byte{ - common.DATA_ACTIVE_SYM: []byte(data.TokenSymbol), - common.DATA_ACTIVE_BAL: []byte(data.Balance), - common.DATA_ACTIVE_DECIMAL: []byte(data.TokenDecimals), - common.DATA_ACTIVE_ADDRESS: []byte(data.ContractAddress), + activeEntries := map[DataTyp][]byte{ + DATA_ACTIVE_SYM: []byte(data.TokenSymbol), + DATA_ACTIVE_BAL: []byte(data.Balance), + DATA_ACTIVE_DECIMAL: []byte(data.TokenDecimals), + DATA_ACTIVE_ADDRESS: []byte(data.ContractAddress), } // Write active data diff --git a/internal/utils/vouchers_test.go b/common/vouchers_test.go similarity index 99% rename from internal/utils/vouchers_test.go rename to common/vouchers_test.go index c59037e..401d4d7 100644 --- a/internal/utils/vouchers_test.go +++ b/common/vouchers_test.go @@ -1,4 +1,4 @@ -package utils +package common import ( "context" diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index ed5f466..2e075d7 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -1117,7 +1117,7 @@ func (h *Handlers) CheckVouchers(ctx context.Context, sym string, input []byte) return res, nil } - data := utils.ProcessVouchers(vouchersResp) + data := common.ProcessVouchers(vouchersResp) // Store all voucher data dataMap := map[string]string{ @@ -1167,7 +1167,7 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r return res, nil } - metadata, err := utils.GetVoucherData(ctx, h.prefixDb, inputStr) + metadata, err := common.GetVoucherData(ctx, h.prefixDb, inputStr) if err != nil { return res, fmt.Errorf("failed to retrieve voucher data: %v", err) } @@ -1177,7 +1177,7 @@ func (h *Handlers) ViewVoucher(ctx context.Context, sym string, input []byte) (r return res, nil } - if err := utils.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { + if err := common.StoreTemporaryVoucher(ctx, h.userdataStore, sessionId, metadata); err != nil { return res, err } @@ -1198,13 +1198,13 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re // Get temporary data - tempData, err := utils.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) + tempData, err := common.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) if err != nil { return res, err } // Set as active and clear temporary data - if err := utils.UpdateVoucherData(ctx, h.userdataStore, sessionId, tempData); err != nil { + if err := common.UpdateVoucherData(ctx, h.userdataStore, sessionId, tempData); err != nil { return res, err } From 0b4bf58107cdbcc1c826eb3d8f0e63073335c0f1 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 31 Oct 2024 16:31:29 +0300 Subject: [PATCH 55/86] resolved failing tests due to tempData --- internal/handlers/ussd/menuhandler_test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index a960cfc..6672ab1 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -2119,14 +2119,6 @@ func TestSetVoucher(t *testing.T) { utils.DATA_ACTIVE_ADDRESS: []byte(tempData.ContractAddress), } - // Define the temporary entries to be cleared - tempEntries := map[utils.DataTyp][]byte{ - utils.DATA_TEMPORARY_SYM: []byte(""), - utils.DATA_TEMPORARY_BAL: []byte(""), - utils.DATA_TEMPORARY_DECIMAL: []byte(""), - utils.DATA_TEMPORARY_ADDRESS: []byte(""), - } - // Mocking ReadEntry calls for temporary data retrieval mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM).Return([]byte(tempData.TokenSymbol), nil) mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL).Return([]byte(tempData.Balance), nil) @@ -2138,11 +2130,6 @@ func TestSetVoucher(t *testing.T) { mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil) } - // Mocking WriteEntry calls for clearing temporary data - for key, value := range tempEntries { - mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil) - } - h := &Handlers{ userdataStore: mockDataStore, } From ac0b4b2ed1de7ab609441b67feaba1c5a58fcafe Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:08:30 +0300 Subject: [PATCH 56/86] pass context --- internal/testutil/TestEngine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/testutil/TestEngine.go b/internal/testutil/TestEngine.go index bd6bc7f..26b889e 100644 --- a/internal/testutil/TestEngine.go +++ b/internal/testutil/TestEngine.go @@ -73,7 +73,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userDataStore) lhs.SetPersister(pe) From 12825ae08a268db47ce105271c41807d1130913a Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:10:46 +0300 Subject: [PATCH 57/86] setup adminstore in the local handler service --- internal/handlers/handlerservice.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 247e6c5..5990dc8 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -1,6 +1,8 @@ package handlers import ( + "context" + "git.defalsify.org/vise.git/asm" "git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/engine" @@ -34,16 +36,21 @@ type LocalHandlerService struct { Rs resource.Resource } -func NewLocalHandlerService(fp string, debug bool, dbResource *resource.DbResource, cfg engine.Config, rs resource.Resource) (*LocalHandlerService, error) { +func NewLocalHandlerService(ctx context.Context, fp string, debug bool, dbResource *resource.DbResource, cfg engine.Config, rs resource.Resource) (*LocalHandlerService, error) { parser, err := getParser(fp, debug) if err != nil { return nil, err } + adminstore, err := utils.NewAdminStore(ctx, "admin_numbers") + if err != nil { + return nil, err + } return &LocalHandlerService{ - Parser: parser, - DbRs: dbResource, - Cfg: cfg, - Rs: rs, + Parser: parser, + DbRs: dbResource, + AdminStore: adminstore, + Cfg: cfg, + Rs: rs, }, nil } From 5abe9b78cc66181271cc4fdacfd305df558474b3 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:11:26 +0300 Subject: [PATCH 58/86] attach an admin store for the phone numbers --- cmd/africastalking/main.go | 8 +++++++- cmd/async/main.go | 9 ++++++++- cmd/http/main.go | 9 ++++++++- cmd/main.go | 13 +++++++------ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 79fb091..ad56467 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -131,7 +131,7 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx,pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) if err != nil { @@ -139,6 +139,12 @@ func main() { os.Exit(1) } + err = lhs.AdminStore.Seed() + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/async/main.go b/cmd/async/main.go index 902dfc7..bdb17a6 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -104,8 +104,15 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) + + err = lhs.AdminStore.Seed() + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) diff --git a/cmd/http/main.go b/cmd/http/main.go index ece882e..39e311e 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -92,13 +92,20 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx,pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } + + err = lhs.AdminStore.Seed() + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/main.go b/cmd/main.go index 7dd3cd6..95b84c9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -15,7 +15,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/handlers" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/internal/utils" ) var ( @@ -49,9 +48,6 @@ func main() { ctx = context.WithValue(ctx, "Database", database) pfp := path.Join(scriptDir, "pp.csv") - as, _ := utils.NewAdminStore(ctx, "admin_numbers") - as.Seed() - cfg := engine.Config{ Root: "root", SessionId: sessionId, @@ -92,9 +88,8 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdatastore) - lhs.SetAdminStore(as) lhs.SetPersister(pe) if err != nil { @@ -102,6 +97,12 @@ func main() { os.Exit(1) } + err = lhs.AdminStore.Seed() + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { From b2655b7f117fa5e0c34d5be2e474d902d31df596 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:59:11 +0300 Subject: [PATCH 59/86] remove seed from executable --- cmd/africastalking/main.go | 8 +------- cmd/async/main.go | 6 ------ cmd/http/main.go | 8 +------- cmd/main.go | 6 ------ 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index ad56467..891301a 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -131,7 +131,7 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(ctx,pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) if err != nil { @@ -139,12 +139,6 @@ func main() { os.Exit(1) } - err = lhs.AdminStore.Seed() - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/async/main.go b/cmd/async/main.go index bdb17a6..df11dac 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -107,12 +107,6 @@ func main() { lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) - err = lhs.AdminStore.Seed() - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) diff --git a/cmd/http/main.go b/cmd/http/main.go index 39e311e..df37878 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -92,7 +92,7 @@ func main() { os.Exit(1) } - lhs, err := handlers.NewLocalHandlerService(ctx,pfp, true, dbResource, cfg, rs) + lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs) lhs.SetDataStore(&userdataStore) if err != nil { @@ -100,12 +100,6 @@ func main() { os.Exit(1) } - err = lhs.AdminStore.Seed() - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { diff --git a/cmd/main.go b/cmd/main.go index 95b84c9..848068f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -97,12 +97,6 @@ func main() { os.Exit(1) } - err = lhs.AdminStore.Seed() - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - accountService := server.AccountService{} hl, err := lhs.GetHandler(&accountService) if err != nil { From 299534ccf1701bf2cbddc7cb68ac34d846745e33 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:59:51 +0300 Subject: [PATCH 60/86] define seed as a command in the devtool --- devtools/commands/seed.go | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 devtools/commands/seed.go diff --git a/devtools/commands/seed.go b/devtools/commands/seed.go new file mode 100644 index 0000000..8abd50f --- /dev/null +++ b/devtools/commands/seed.go @@ -0,0 +1,47 @@ +package commands + +import ( + "context" + "encoding/json" + "os" + + "git.defalsify.org/vise.git/logging" + "git.grassecon.net/urdt/ussd/internal/utils" +) + +var ( + logg = logging.NewVanilla().WithDomain("adminstore") +) + +type Admin struct { + PhoneNumber string `json:"phonenumber"` +} + +type Config struct { + Admins []Admin `json:"admins"` +} + +func Seed(ctx context.Context) error { + var config Config + adminstore, err := utils.NewAdminStore(ctx, "admin_numbers") + store := adminstore.FsStore + if err != nil { + return err + } + defer store.Close() + data, err := os.ReadFile("admin_numbers.json") + if err != nil { + return err + } + if err := json.Unmarshal(data, &config); err != nil { + return err + } + for _, admin := range config.Admins { + err := store.Put(ctx, []byte(admin.PhoneNumber), []byte("1")) + if err != nil { + logg.Printf(logging.LVL_DEBUG, "Failed to insert admin number", admin.PhoneNumber) + return err + } + } + return nil +} From 7aab3cff8ca8dda7feafb2fba15d71bf601f8894 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 21:00:16 +0300 Subject: [PATCH 61/86] remove seed --- internal/utils/adminstore.go | 40 +++--------------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/internal/utils/adminstore.go b/internal/utils/adminstore.go index 43a3bfd..a492479 100644 --- a/internal/utils/adminstore.go +++ b/internal/utils/adminstore.go @@ -2,8 +2,6 @@ package utils import ( "context" - "encoding/json" - "os" "git.defalsify.org/vise.git/db" fsdb "git.defalsify.org/vise.git/db/fs" @@ -14,17 +12,9 @@ var ( logg = logging.NewVanilla().WithDomain("adminstore") ) -type Admin struct { - PhoneNumber string `json:"phonenumber"` -} - -type Config struct { - Admins []Admin `json:"admins"` -} - type AdminStore struct { ctx context.Context - fsStore db.Db + FsStore db.Db } func NewAdminStore(ctx context.Context, fileName string) (*AdminStore, error) { @@ -32,7 +22,7 @@ func NewAdminStore(ctx context.Context, fileName string) (*AdminStore, error) { if err != nil { return nil, err } - return &AdminStore{ctx: ctx, fsStore: fsStore}, nil + return &AdminStore{ctx: ctx, FsStore: fsStore}, nil } func getFsStore(ctx context.Context, connectStr string) (db.Db, error) { @@ -45,33 +35,9 @@ func getFsStore(ctx context.Context, connectStr string) (db.Db, error) { return fsStore, nil } -// Seed initializes a list of phonenumbers with admin privileges -func (as *AdminStore) Seed() error { - var config Config - - store := as.fsStore - defer store.Close() - - data, err := os.ReadFile("admin_numbers.json") - if err != nil { - return err - } - if err := json.Unmarshal(data, &config); err != nil { - return err - } - for _, admin := range config.Admins { - err := store.Put(as.ctx, []byte(admin.PhoneNumber), []byte("1")) - if err != nil { - logg.Printf(logging.LVL_DEBUG, "Failed to insert admin number", admin.PhoneNumber) - return err - } - } - return nil -} - // Checks if the given sessionId is listed as an admin. func (as *AdminStore) IsAdmin(sessionId string) (bool, error) { - _, err := as.fsStore.Get(as.ctx, []byte(sessionId)) + _, err := as.FsStore.Get(as.ctx, []byte(sessionId)) if err != nil { if db.IsNotFound(err) { logg.Printf(logging.LVL_INFO, "Returning false because session id was not found") From 7fa38340ddf3cfaab0207506d048db32bf82dc52 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 21:00:41 +0300 Subject: [PATCH 62/86] add command to initialize a list of admin numbers --- devtools/main.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 devtools/main.go diff --git a/devtools/main.go b/devtools/main.go new file mode 100644 index 0000000..d0d4632 --- /dev/null +++ b/devtools/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "context" + "log" + + "git.grassecon.net/urdt/ussd/devtools/commands" +) + +func main() { + ctx := context.Background() + err := commands.Seed(ctx) + if err != nil { + log.Fatalf("Failed to initialize a list of admins with error %s", err) + } + +} From 53fa6f64ce209bac95129a1815f1edcd01ff369e Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 21:01:01 +0300 Subject: [PATCH 63/86] define structure of json --- devtools/admin_numbers.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 devtools/admin_numbers.json diff --git a/devtools/admin_numbers.json b/devtools/admin_numbers.json new file mode 100644 index 0000000..ca58a23 --- /dev/null +++ b/devtools/admin_numbers.json @@ -0,0 +1,7 @@ +{ + "admins": [ + { + "phonenumber" : "" + } + ] +} \ No newline at end of file From 7d1a04f089547c90b04d328a99298cb2bc24de99 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 21:01:24 +0300 Subject: [PATCH 64/86] remove from root --- admin_numbers.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 admin_numbers.json diff --git a/admin_numbers.json b/admin_numbers.json deleted file mode 100644 index ca58a23..0000000 --- a/admin_numbers.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "admins": [ - { - "phonenumber" : "" - } - ] -} \ No newline at end of file From f4ca4454ea2f61aa798f13253b011dcd414a94ab Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 1 Nov 2024 00:42:23 +0300 Subject: [PATCH 65/86] use a single DATA_TEMPORARY_VALUE for the PIN and voucher data --- internal/handlers/ussd/menuhandler.go | 8 ++-- internal/handlers/ussd/menuhandler_test.go | 26 +++++-------- internal/utils/db.go | 6 +-- internal/utils/vouchers.go | 43 +++++++--------------- internal/utils/vouchers_test.go | 17 +++------ 5 files changed, 34 insertions(+), 66 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dd3efdb..aaa1530 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -222,7 +222,7 @@ func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) ( return res, nil } -// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_PIN +// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_VALUE // during the account creation process // and during the change PIN process func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { @@ -247,7 +247,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagReset = append(res.FlagReset, flag_incorrect_pin) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(accountPIN)) if err != nil { return res, err } @@ -264,7 +264,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -295,7 +295,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 6672ab1..bf29926 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,8 +19,8 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" + "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" @@ -271,7 +271,7 @@ func TestSaveTemporaryPin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -1013,7 +1013,7 @@ func TestVerifyCreatePin(t *testing.T) { }, } - typ := utils.DATA_TEMPORARY_PIN + typ := utils.DATA_TEMPORARY_VALUE for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1806,7 +1806,7 @@ func TestConfirmPin(t *testing.T) { // Set up the expected behavior of the mock mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) + mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) @@ -2078,16 +2078,9 @@ func TestViewVoucher(t *testing.T) { } // Set up expectations for mockDataStore - expectedData := map[utils.DataTyp]string{ - utils.DATA_TEMPORARY_SYM: "SRF", - utils.DATA_TEMPORARY_BAL: "100", - utils.DATA_TEMPORARY_DECIMAL: "6", - utils.DATA_TEMPORARY_ADDRESS: "0xd4c288865Ce", - } + expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce") - for dataType, dataValue := range expectedData { - mockDataStore.On("WriteEntry", ctx, sessionId, dataType, []byte(dataValue)).Return(nil) - } + mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) @@ -2111,6 +2104,8 @@ func TestSetVoucher(t *testing.T) { ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", } + expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9") + // Define the expected active entries activeEntries := map[utils.DataTyp][]byte{ utils.DATA_ACTIVE_SYM: []byte(tempData.TokenSymbol), @@ -2120,10 +2115,7 @@ func TestSetVoucher(t *testing.T) { } // Mocking ReadEntry calls for temporary data retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM).Return([]byte(tempData.TokenSymbol), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL).Return([]byte(tempData.Balance), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_DECIMAL).Return([]byte(tempData.TokenDecimals), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_ADDRESS).Return([]byte(tempData.ContractAddress), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) // Mocking WriteEntry calls for setting active data for key, value := range activeEntries { diff --git a/internal/utils/db.go b/internal/utils/db.go index 802e092..df96dfa 100644 --- a/internal/utils/db.go +++ b/internal/utils/db.go @@ -22,16 +22,12 @@ const ( DATA_OFFERINGS DATA_RECIPIENT DATA_AMOUNT - DATA_TEMPORARY_PIN + DATA_TEMPORARY_VALUE DATA_VOUCHER_LIST - DATA_TEMPORARY_SYM DATA_ACTIVE_SYM - DATA_TEMPORARY_BAL DATA_ACTIVE_BAL DATA_PUBLIC_KEY_REVERSE - DATA_TEMPORARY_DECIMAL DATA_ACTIVE_DECIMAL - DATA_TEMPORARY_ADDRESS DATA_ACTIVE_ADDRESS ) diff --git a/internal/utils/vouchers.go b/internal/utils/vouchers.go index b027cc1..1c20492 100644 --- a/internal/utils/vouchers.go +++ b/internal/utils/vouchers.go @@ -77,7 +77,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, for i, sym := range symList { parts := strings.SplitN(sym, ":", 2) - + if input == parts[0] || strings.EqualFold(input, parts[1]) { symbol = parts[1] if i < len(balList) { @@ -97,45 +97,30 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, // StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore. func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { - entries := map[DataTyp][]byte{ - DATA_TEMPORARY_SYM: []byte(data.TokenSymbol), - DATA_TEMPORARY_BAL: []byte(data.Balance), - DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals), - DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress), + tempData := fmt.Sprintf("%s,%s,%s,%s", data.TokenSymbol, data.Balance, data.TokenDecimals, data.ContractAddress) + + if err := store.WriteEntry(ctx, sessionId, DATA_TEMPORARY_VALUE, []byte(tempData)); err != nil { + return err } - for key, value := range entries { - if err := store.WriteEntry(ctx, sessionId, key, value); err != nil { - return err - } - } return nil } // GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore. func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) { - keys := []DataTyp{ - DATA_TEMPORARY_SYM, - DATA_TEMPORARY_BAL, - DATA_TEMPORARY_DECIMAL, - DATA_TEMPORARY_ADDRESS, + temp_data, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE) + if err != nil { + return nil, err } + values := strings.SplitN(string(temp_data), ",", 4) + data := &dataserviceapi.TokenHoldings{} - values := make([][]byte, len(keys)) - for i, key := range keys { - value, err := store.ReadEntry(ctx, sessionId, key) - if err != nil { - return nil, err - } - values[i] = value - } - - data.TokenSymbol = string(values[0]) - data.Balance = string(values[1]) - data.TokenDecimals = string(values[2]) - data.ContractAddress = string(values[3]) + data.TokenSymbol = values[0] + data.Balance = values[1] + data.TokenDecimals = values[2] + data.ContractAddress = values[3] return data, nil } diff --git a/internal/utils/vouchers_test.go b/internal/utils/vouchers_test.go index a609d27..c2ff4e3 100644 --- a/internal/utils/vouchers_test.go +++ b/internal/utils/vouchers_test.go @@ -2,6 +2,7 @@ package utils import ( "context" + "fmt" "testing" "git.grassecon.net/urdt/ussd/internal/storage" @@ -126,18 +127,12 @@ func TestStoreTemporaryVoucher(t *testing.T) { require.NoError(t, err) // Verify stored data - expectedEntries := map[DataTyp][]byte{ - DATA_TEMPORARY_SYM: []byte("SRF"), - DATA_TEMPORARY_BAL: []byte("200"), - DATA_TEMPORARY_DECIMAL: []byte("6"), - DATA_TEMPORARY_ADDRESS: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"), - } + expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9") + + storedValue, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE) + require.NoError(t, err) + require.Equal(t, expectedData, string(storedValue), "Mismatch for key %v", DATA_TEMPORARY_VALUE) - for key, expectedValue := range expectedEntries { - storedValue, err := store.ReadEntry(ctx, sessionId, key) - require.NoError(t, err) - require.Equal(t, expectedValue, storedValue, "Mismatch for key %v", key) - } } func TestGetTemporaryVoucherData(t *testing.T) { From 63eed81d3d5ccb0c9433eda7b9fd289463c6d4f0 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 1 Nov 2024 00:44:15 +0300 Subject: [PATCH 66/86] Merge branch 'master' into consolidate-temp-data-storage --- internal/handlers/ussd/menuhandler.go | 118 +++++++++++++------- internal/handlers/ussd/menuhandler_test.go | 52 +++++++-- internal/utils/db.go | 7 ++ services/registration/enter_familyname.vis | 2 +- services/registration/enter_location.vis | 2 +- services/registration/enter_name.vis | 2 +- services/registration/enter_offerings.vis | 2 +- services/registration/enter_yob.vis | 4 +- services/registration/set_female.vis | 2 +- services/registration/set_male.vis | 2 +- services/registration/set_unspecified.vis | 2 +- services/registration/update_age | 2 + services/registration/update_familyname.vis | 2 + services/registration/update_firstname.vis | 2 + services/registration/update_gender.vis | 2 + services/registration/update_location.vis | 2 + services/registration/update_offerings.vis | 2 + services/registration/update_yob.vis | 2 + 18 files changed, 150 insertions(+), 59 deletions(-) create mode 100644 services/registration/update_age create mode 100644 services/registration/update_familyname.vis create mode 100644 services/registration/update_firstname.vis create mode 100644 services/registration/update_gender.vis create mode 100644 services/registration/update_location.vis create mode 100644 services/registration/update_offerings.vis create mode 100644 services/registration/update_yob.vis diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index aaa1530..60dd11c 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -19,9 +19,9 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.grassecon.net/urdt/ussd/common" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/utils" - "git.grassecon.net/urdt/ussd/common" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -33,7 +33,6 @@ var ( translationDir = path.Join(scriptDir, "locale") okResponse *api.OKResponse errResponse *api.ErrResponse - backOption = []byte("0") ) // FlagManager handles centralized flag management @@ -334,13 +333,18 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil + firstName := string(input) + store := h.userdataStore + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + if allowUpdate { + temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME) + err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName)) + if err != nil { + return res, err } - firstName := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)) if err != nil { return res, err } @@ -357,20 +361,24 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil - } - familyName := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) + store := h.userdataStore + familyName := string(input) + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME) + err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) if err != nil { return res, err } } else { - return res, fmt.Errorf("a family name cannot be less than one character") + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)) + if err != nil { + return res, err + } } - return res, nil } @@ -382,10 +390,19 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou if !ok { return res, fmt.Errorf("missing session") } - if len(input) == 4 { - yob := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(yob)) + yob := string(input) + store := h.userdataStore + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB) + err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob)) + if err != nil { + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)) if err != nil { return res, err } @@ -402,13 +419,20 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil + location := string(input) + store := h.userdataStore + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION) + err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation)) + if err != nil { + return res, err } - location := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(location)) if err != nil { return res, err } @@ -426,14 +450,22 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re if !ok { return res, fmt.Errorf("missing session") } - if bytes.Equal(input, backOption) { - return res, nil - } gender := strings.Split(symbol, "_")[1] store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) - if err != nil { - return res, nil + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER) + err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender)) + if err != nil { + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(gender)) + if err != nil { + return res, err + } } return res, nil @@ -447,12 +479,22 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - offerings := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)) + offerings := string(input) + store := h.userdataStore + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS) + err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings)) if err != nil { - return res, nil + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)) + if err != nil { + return res, err } } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index bf29926..f6f1069 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -174,8 +174,11 @@ func TestWithPersister_PanicWhenAlreadySet(t *testing.T) { } func TestSaveFirstname(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create new mocks mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -183,11 +186,13 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + flagManager: fm.parser, + st: mockState, } // Call the method @@ -204,6 +209,9 @@ func TestSaveFirstname(t *testing.T) { func TestSaveFamilyname(t *testing.T) { // Create a new instance of UserDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -211,11 +219,13 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -288,8 +298,11 @@ func TestSaveTemporaryPin(t *testing.T) { } func TestSaveYoB(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create new instances mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -297,11 +310,13 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_YOB, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -318,6 +333,9 @@ func TestSaveYoB(t *testing.T) { func TestSaveLocation(t *testing.T) { // Create a new instance of MockMyDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -325,11 +343,13 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_LOCATION, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -346,6 +366,9 @@ func TestSaveLocation(t *testing.T) { func TestSaveOfferings(t *testing.T) { // Create a new instance of MockUserDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -353,11 +376,13 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -372,10 +397,12 @@ func TestSaveOfferings(t *testing.T) { } func TestSaveGender(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create a new mock instances mockStore := new(mocks.MockUserDataStore) mockState := state.NewState(16) + fm, _ := NewFlagManager(flagsPath) + // Define the session ID and context sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) @@ -415,16 +442,17 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { - expectedKey := utils.DATA_GENDER + expectedKey := utils.DATA_TEMPORARY_GENDER mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, st: mockState, + flagManager: fm.parser, } // Call the method @@ -435,9 +463,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) } }) } diff --git a/internal/utils/db.go b/internal/utils/db.go index df96dfa..4d29c48 100644 --- a/internal/utils/db.go +++ b/internal/utils/db.go @@ -14,11 +14,17 @@ const ( DATA_CUSTODIAL_ID DATA_ACCOUNT_PIN DATA_ACCOUNT_STATUS + DATA_TEMPORARY_FIRST_NAME DATA_FIRST_NAME + DATA_TEMPORARY_FAMILY_NAME DATA_FAMILY_NAME + DATA_TEMPORARY_YOB DATA_YOB + DATA_TEMPORARY_LOCATION DATA_LOCATION + DATA_TEMPORARY_GENDER DATA_GENDER + DATA_TEMPORARY_OFFERINGS DATA_OFFERINGS DATA_RECIPIENT DATA_AMOUNT @@ -29,6 +35,7 @@ const ( DATA_PUBLIC_KEY_REVERSE DATA_ACTIVE_DECIMAL DATA_ACTIVE_ADDRESS + ) func typToBytes(typ DataTyp) []byte { diff --git a/services/registration/enter_familyname.vis b/services/registration/enter_familyname.vis index 5a684ed..5db4c17 100644 --- a/services/registration/enter_familyname.vis +++ b/services/registration/enter_familyname.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_familyname flag_allow_update 1 MOUT back 0 HALT LOAD save_familyname 0 diff --git a/services/registration/enter_location.vis b/services/registration/enter_location.vis index c8da2dd..8966872 100644 --- a/services/registration/enter_location.vis +++ b/services/registration/enter_location.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_location flag_allow_update 1 MOUT back 0 HALT LOAD save_location 0 diff --git a/services/registration/enter_name.vis b/services/registration/enter_name.vis index 799b2a1..f853d0a 100644 --- a/services/registration/enter_name.vis +++ b/services/registration/enter_name.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_firstname flag_allow_update 1 MOUT back 0 HALT LOAD save_firstname 0 diff --git a/services/registration/enter_offerings.vis b/services/registration/enter_offerings.vis index 26e4b61..5cc7977 100644 --- a/services/registration/enter_offerings.vis +++ b/services/registration/enter_offerings.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_offerings flag_allow_update 1 LOAD save_offerings 0 MOUT back 0 HALT diff --git a/services/registration/enter_yob.vis b/services/registration/enter_yob.vis index 40bf3f4..c74aeed 100644 --- a/services/registration/enter_yob.vis +++ b/services/registration/enter_yob.vis @@ -1,10 +1,10 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 -LOAD save_yob 0 +CATCH update_yob flag_allow_update 1 MOUT back 0 HALT LOAD verify_yob 0 CATCH incorrect_date_format flag_incorrect_date_format 1 +LOAD save_yob 0 RELOAD save_yob INCMP _ 0 INCMP pin_entry * diff --git a/services/registration/set_female.vis b/services/registration/set_female.vis index 723b080..e211ada 100644 --- a/services/registration/set_female.vis +++ b/services/registration/set_female.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/set_male.vis b/services/registration/set_male.vis index 723b080..e211ada 100644 --- a/services/registration/set_male.vis +++ b/services/registration/set_male.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/set_unspecified.vis b/services/registration/set_unspecified.vis index 723b080..e211ada 100644 --- a/services/registration/set_unspecified.vis +++ b/services/registration/set_unspecified.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/update_age b/services/registration/update_age new file mode 100644 index 0000000..76ca306 --- /dev/null +++ b/services/registration/update_age @@ -0,0 +1,2 @@ +RELOAD save_yob +CATCH profile_update_success flag_allow_update 1 \ No newline at end of file diff --git a/services/registration/update_familyname.vis b/services/registration/update_familyname.vis new file mode 100644 index 0000000..7cd4d9f --- /dev/null +++ b/services/registration/update_familyname.vis @@ -0,0 +1,2 @@ +RELOAD save_familyname +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_firstname.vis b/services/registration/update_firstname.vis new file mode 100644 index 0000000..dca7036 --- /dev/null +++ b/services/registration/update_firstname.vis @@ -0,0 +1,2 @@ +RELOAD save_firstname +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_gender.vis b/services/registration/update_gender.vis new file mode 100644 index 0000000..506a56a --- /dev/null +++ b/services/registration/update_gender.vis @@ -0,0 +1,2 @@ +RELOAD save_gender +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_location.vis b/services/registration/update_location.vis new file mode 100644 index 0000000..16c4ea2 --- /dev/null +++ b/services/registration/update_location.vis @@ -0,0 +1,2 @@ +RELOAD save_location +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_offerings.vis b/services/registration/update_offerings.vis new file mode 100644 index 0000000..4aeed74 --- /dev/null +++ b/services/registration/update_offerings.vis @@ -0,0 +1,2 @@ +RELOAD save_offerings +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_yob.vis b/services/registration/update_yob.vis new file mode 100644 index 0000000..a9388ae --- /dev/null +++ b/services/registration/update_yob.vis @@ -0,0 +1,2 @@ +RELOAD save_yob +CATCH profile_update_success flag_allow_update 1 From d7ea8fa65196e1de6fd1c08f4f0a408de1166ba8 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 1 Nov 2024 01:10:58 +0300 Subject: [PATCH 67/86] Use the DATA_TEMPORARY_VALUE for the user data --- internal/handlers/ussd/menuhandler.go | 24 +++++++++++----------- internal/handlers/ussd/menuhandler_test.go | 18 ++++++++-------- internal/utils/db.go | 6 ------ 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 60dd11c..5f0c2d9 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -338,13 +338,13 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME) + temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)) if err != nil { return res, err } @@ -368,13 +368,13 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME) + temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)) if err != nil { return res, err } @@ -396,13 +396,13 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB) + temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)) if err != nil { return res, err } @@ -426,13 +426,13 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION) + temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(location)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location)) if err != nil { return res, err } @@ -456,13 +456,13 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER) + temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(gender)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(gender)) if err != nil { return res, err } @@ -486,13 +486,13 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS) + temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index f6f1069..77ae68c 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -186,7 +186,7 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -219,7 +219,7 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -310,7 +310,7 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -343,7 +343,7 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -376,7 +376,7 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -442,10 +442,10 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { - expectedKey := utils.DATA_TEMPORARY_GENDER + expectedKey := utils.DATA_TEMPORARY_VALUE mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store @@ -463,9 +463,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } }) } diff --git a/internal/utils/db.go b/internal/utils/db.go index 4d29c48..b37240d 100644 --- a/internal/utils/db.go +++ b/internal/utils/db.go @@ -14,17 +14,11 @@ const ( DATA_CUSTODIAL_ID DATA_ACCOUNT_PIN DATA_ACCOUNT_STATUS - DATA_TEMPORARY_FIRST_NAME DATA_FIRST_NAME - DATA_TEMPORARY_FAMILY_NAME DATA_FAMILY_NAME - DATA_TEMPORARY_YOB DATA_YOB - DATA_TEMPORARY_LOCATION DATA_LOCATION - DATA_TEMPORARY_GENDER DATA_GENDER - DATA_TEMPORARY_OFFERINGS DATA_OFFERINGS DATA_RECIPIENT DATA_AMOUNT From 9a528cfd1440f72d0678d318e847e7d10fbdee69 Mon Sep 17 00:00:00 2001 From: lash Date: Fri, 1 Nov 2024 03:17:01 +0000 Subject: [PATCH 68/86] Clean up messily failed conflict resolution --- common/vouchers_test.go | 17 +++-- internal/handlers/ussd/menuhandler.go | 44 ++++++------- internal/handlers/ussd/menuhandler_test.go | 74 ++++------------------ 3 files changed, 44 insertions(+), 91 deletions(-) diff --git a/common/vouchers_test.go b/common/vouchers_test.go index 95fce6e..8b9fa2a 100644 --- a/common/vouchers_test.go +++ b/common/vouchers_test.go @@ -9,13 +9,12 @@ import ( "github.com/stretchr/testify/require" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/common" memdb "git.defalsify.org/vise.git/db/mem" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) // InitializeTestDb sets up and returns an in-memory database and store. -func InitializeTestDb(t *testing.T) (context.Context, *common.UserDataStore) { +func InitializeTestDb(t *testing.T) (context.Context, *UserDataStore) { ctx := context.Background() // Initialize memDb @@ -23,8 +22,8 @@ func InitializeTestDb(t *testing.T) (context.Context, *common.UserDataStore) { err := db.Connect(ctx, "") require.NoError(t, err, "Failed to connect to memDb") - // Create common.UserDataStore with memDb - store := &common.UserDataStore{Db: db} + // Create UserDataStore with memDb + store := &UserDataStore{Db: db} t.Cleanup(func() { db.Close() // Ensure the DB is closed after each test @@ -183,11 +182,11 @@ func TestUpdateVoucherData(t *testing.T) { require.NoError(t, err) // Verify active data was stored correctly - activeEntries := map[common.DataTyp][]byte{ - common.DATA_ACTIVE_SYM: []byte(newData.TokenSymbol), - common.DATA_ACTIVE_BAL: []byte(newData.Balance), - common.DATA_ACTIVE_DECIMAL: []byte(newData.TokenDecimals), - common.DATA_ACTIVE_ADDRESS: []byte(newData.ContractAddress), + activeEntries := map[DataTyp][]byte{ + DATA_ACTIVE_SYM: []byte(newData.TokenSymbol), + DATA_ACTIVE_BAL: []byte(newData.Balance), + DATA_ACTIVE_DECIMAL: []byte(newData.TokenDecimals), + DATA_ACTIVE_ADDRESS: []byte(newData.ContractAddress), } for key, expectedValue := range activeEntries { diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index db8d520..42785d7 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -20,7 +20,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/internal/handlers/server" + "git.grassecon.net/urdt/ussd/remote" "git.grassecon.net/urdt/ussd/internal/utils" "gopkg.in/leonelquinteros/gotext.v1" @@ -246,7 +246,7 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt res.FlagReset = append(res.FlagReset, flag_incorrect_pin) store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(accountPIN)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(accountPIN)) if err != nil { return res, err } @@ -263,7 +263,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -294,7 +294,7 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte return res, fmt.Errorf("missing session") } store := h.userdataStore - temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -338,13 +338,13 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName)) + temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_FIRST_NAME, []byte(temporaryFirstName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(firstName)) if err != nil { return res, err } @@ -369,13 +369,13 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) + temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(familyName)) if err != nil { return res, err } @@ -397,13 +397,13 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob)) + temporaryYob, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_YOB, []byte(temporaryYob)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)) if err != nil { return res, err } @@ -427,13 +427,13 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation)) + temporaryLocation, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_LOCATION, []byte(temporaryLocation)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(location)) if err != nil { return res, err } @@ -457,13 +457,13 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender)) + temporaryGender, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_GENDER, []byte(temporaryGender)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(gender)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(gender)) if err != nil { return res, err } @@ -488,13 +488,13 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) allowUpdate := h.st.MatchFlag(flag_allow_update, true) if allowUpdate { - temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE) - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings)) + temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE) + err = store.WriteEntry(ctx, sessionId, common.DATA_OFFERINGS, []byte(temporaryOfferings)) if err != nil { return res, err } } else { - err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)) + err = store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(offerings)) if err != nil { return res, err } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 30f84d9..2eb6519 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,7 +19,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/testservice" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" // "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" @@ -181,11 +180,7 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FIRST_NAME, []byte(firstName)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -218,11 +213,7 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -284,11 +275,7 @@ func TestSaveTemporaryPin(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -317,11 +304,7 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_YOB, []byte(yob)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -354,11 +337,7 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_LOCATION, []byte(yob)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -391,11 +370,7 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock -<<<<<<< HEAD - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_OFFERINGS, []byte(offerings)).Return(nil) -======= - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ @@ -461,17 +436,10 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { -<<<<<<< HEAD - expectedKey := common.DATA_GENDER + expectedKey := common.DATA_TEMPORARY_VALUE mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) -======= - expectedKey := utils.DATA_TEMPORARY_VALUE - mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) - } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) ->>>>>>> master + mockStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store @@ -489,15 +457,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { -<<<<<<< HEAD - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_GENDER, []byte(tt.expectedGender)) -======= - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) ->>>>>>> master + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) } }) } @@ -1072,11 +1034,7 @@ func TestVerifyCreatePin(t *testing.T) { }, } -<<<<<<< HEAD - typ := common.DATA_TEMPORARY_PIN -======= - typ := utils.DATA_TEMPORARY_VALUE ->>>>>>> master + typ := common.DATA_TEMPORARY_VALUE for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1816,11 +1774,7 @@ func TestConfirmPin(t *testing.T) { // Set up the expected behavior of the mock mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) -<<<<<<< HEAD - mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil) -======= - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) ->>>>>>> master + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) @@ -2060,7 +2014,7 @@ func TestViewVoucher(t *testing.T) { // Set up expectations for mockDataStore expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce") - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) + mockDataStore.On("WriteEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) @@ -2095,7 +2049,7 @@ func TestSetVoucher(t *testing.T) { } // Mocking ReadEntry calls for temporary data retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) + mockDataStore.On("ReadEntry", ctx, sessionId, common.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) // Mocking WriteEntry calls for setting active data for key, value := range activeEntries { From 0014693ba8b3b8f1545e59e3cf66bf6bf71caebb Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 06:39:37 +0300 Subject: [PATCH 69/86] remove guard pin option --- menutraversal_test/group_test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menutraversal_test/group_test.json b/menutraversal_test/group_test.json index 8b765f5..a219a6c 100644 --- a/menutraversal_test/group_test.json +++ b/menutraversal_test/group_test.json @@ -13,7 +13,7 @@ }, { "input": "5", - "expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n3:Guard my PIN\n0:Back" + "expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back" }, { "input": "1", From 7e448f739ab0205b8e3bab16b0081344de573868 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 09:35:48 +0300 Subject: [PATCH 70/86] change fs store path to root --- devtools/commands/seed.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/commands/seed.go b/devtools/commands/seed.go index 8abd50f..e76c83d 100644 --- a/devtools/commands/seed.go +++ b/devtools/commands/seed.go @@ -23,7 +23,7 @@ type Config struct { func Seed(ctx context.Context) error { var config Config - adminstore, err := utils.NewAdminStore(ctx, "admin_numbers") + adminstore, err := utils.NewAdminStore(ctx, "../admin_numbers") store := adminstore.FsStore if err != nil { return err From eb2c73dce1478023a34e2d552a649a9c14339d41 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 11:51:50 +0300 Subject: [PATCH 71/86] remove unused setadmin store --- internal/handlers/handlerservice.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 5990dc8..cbc2a29 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -62,10 +62,6 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { ls.UserdataStore = db } -func (ls *LocalHandlerService) SetAdminStore(adminstore *utils.AdminStore) { - ls.AdminStore = adminstore -} - func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService) if err != nil { From cfe3e526dfb1793ab4977998ae730c834ac67d5e Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Fri, 1 Nov 2024 13:17:45 +0300 Subject: [PATCH 72/86] Remove the subprefixdbmock --- internal/handlers/ussd/menuhandler_test.go | 87 +++++++++++++++------- internal/testutil/mocks/subprefixdbmock.go | 21 ------ 2 files changed, 59 insertions(+), 49 deletions(-) delete mode 100644 internal/testutil/mocks/subprefixdbmock.go diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 77ae68c..6f70108 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -16,6 +16,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" @@ -26,6 +27,7 @@ import ( testdataloader "github.com/peteole/testdata-loader" "github.com/stretchr/testify/require" + memdb "git.defalsify.org/vise.git/db/mem" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) @@ -2021,19 +2023,24 @@ func TestSetDefaultVoucher(t *testing.T) { func TestCheckVouchers(t *testing.T) { mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - mockSubPrefixDb := new(mocks.MockSubPrefixDb) sessionId := "session123" publicKey := "0X13242618721" + ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) h := &Handlers{ userdataStore: mockDataStore, accountService: mockAccountService, - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) mockVouchersResponse := &models.VoucherHoldingResponse{} @@ -2042,38 +2049,53 @@ func TestCheckVouchers(t *testing.T) { {ContractAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, } + expectedSym := []byte("1:SRF\n2:MILO") + mockAccountService.On("FetchVouchers", string(publicKey)).Return(mockVouchersResponse, nil) - mockSubPrefixDb.On("Put", ctx, []byte("sym"), []byte("1:SRF\n2:MILO")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("bal"), []byte("1:100\n2:200")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("deci"), []byte("1:6\n2:4")).Return(nil) - mockSubPrefixDb.On("Put", ctx, []byte("addr"), []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa")).Return(nil) - - _, err := h.CheckVouchers(ctx, "check_vouchers", []byte("")) - + _, err = h.CheckVouchers(ctx, "check_vouchers", []byte("")) assert.NoError(t, err) + // Read voucher sym data from the store + voucherData, err := spdb.Get(ctx, []byte("sym")) + if err != nil { + t.Fatal(err) + } + + // assert that the data is stored correctly + assert.Equal(t, expectedSym, voucherData) + mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) } func TestGetVoucherList(t *testing.T) { - mockSubPrefixDb := new(mocks.MockSubPrefixDb) - sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + h := &Handlers{ - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } - mockSubPrefixDb.On("Get", ctx, []byte("sym")).Return([]byte("1:SRF\n2:MILO"), nil) + expectedSym := []byte("1:SRF\n2:MILO") + + // Put voucher sym data from the store + err = spdb.Put(ctx, []byte("sym"), expectedSym) + if err != nil { + t.Fatal(err) + } res, err := h.GetVoucherList(ctx, "", []byte("")) - assert.NoError(t, err) - assert.Contains(t, res.Content, "1:SRF\n2:MILO") - mockSubPrefixDb.AssertExpectations(t) + assert.NoError(t, err) + assert.Equal(t, res.Content, string(expectedSym)) } func TestViewVoucher(t *testing.T) { @@ -2082,27 +2104,37 @@ func TestViewVoucher(t *testing.T) { t.Logf(err.Error()) } mockDataStore := new(mocks.MockUserDataStore) - mockSubPrefixDb := new(mocks.MockSubPrefixDb) sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) + db := memdb.NewMemDb() + err = db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + h := &Handlers{ userdataStore: mockDataStore, flagManager: fm.parser, - prefixDb: mockSubPrefixDb, + prefixDb: spdb, } // Define mock voucher data - mockVoucherData := map[string]string{ - "sym": "1:SRF", - "bal": "1:100", - "deci": "1:6", - "addr": "1:0xd4c288865Ce", + mockData := map[string][]byte{ + "sym": []byte("1:SRF\n2:MILO"), + "bal": []byte("1:100\n2:200"), + "deci": []byte("1:6\n2:4"), + "addr": []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), } - for key, value := range mockVoucherData { - mockSubPrefixDb.On("Get", ctx, []byte(key)).Return([]byte(value), nil) + // Put the data + for key, value := range mockData { + err = spdb.Put(ctx, []byte(key), []byte(value)) + if err != nil { + t.Fatal(err) + } } // Set up expectations for mockDataStore @@ -2115,7 +2147,6 @@ func TestViewVoucher(t *testing.T) { assert.Contains(t, res.Content, "SRF\n100") mockDataStore.AssertExpectations(t) - mockSubPrefixDb.AssertExpectations(t) } func TestSetVoucher(t *testing.T) { diff --git a/internal/testutil/mocks/subprefixdbmock.go b/internal/testutil/mocks/subprefixdbmock.go deleted file mode 100644 index e98bcb6..0000000 --- a/internal/testutil/mocks/subprefixdbmock.go +++ /dev/null @@ -1,21 +0,0 @@ -package mocks - -import ( - "context" - - "github.com/stretchr/testify/mock" -) - -type MockSubPrefixDb struct { - mock.Mock -} - -func (m *MockSubPrefixDb) Get(ctx context.Context, key []byte) ([]byte, error) { - args := m.Called(ctx, key) - return args.Get(0).([]byte), args.Error(1) -} - -func (m *MockSubPrefixDb) Put(ctx context.Context, key, val []byte) error { - args := m.Called(ctx, key, val) - return args.Error(0) -} From 332074375aee0010d9cbf37f8738bf12e432810d Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 16:44:54 +0300 Subject: [PATCH 73/86] wrap in devtools/admin --- devtools/{ => admin}/admin_numbers.json | 0 devtools/{ => admin}/commands/seed.go | 0 devtools/{ => admin}/main.go | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename devtools/{ => admin}/admin_numbers.json (100%) rename devtools/{ => admin}/commands/seed.go (100%) rename devtools/{ => admin}/main.go (79%) diff --git a/devtools/admin_numbers.json b/devtools/admin/admin_numbers.json similarity index 100% rename from devtools/admin_numbers.json rename to devtools/admin/admin_numbers.json diff --git a/devtools/commands/seed.go b/devtools/admin/commands/seed.go similarity index 100% rename from devtools/commands/seed.go rename to devtools/admin/commands/seed.go diff --git a/devtools/main.go b/devtools/admin/main.go similarity index 79% rename from devtools/main.go rename to devtools/admin/main.go index d0d4632..9a527f3 100644 --- a/devtools/main.go +++ b/devtools/admin/main.go @@ -4,7 +4,7 @@ import ( "context" "log" - "git.grassecon.net/urdt/ussd/devtools/commands" + "git.grassecon.net/urdt/ussd/devtools/admin/commands" ) func main() { From 6dbe74d12bc777285b68837fc9c4d0b470559607 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 16:46:09 +0300 Subject: [PATCH 74/86] use single temporary value --- internal/handlers/ussd/menuhandler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 198d45b..feb002e 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -237,7 +237,7 @@ func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byt if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -312,7 +312,7 @@ func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input if err != nil { return res, err } - err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) if err != nil { return res, err } @@ -845,7 +845,7 @@ func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_PIN) + temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_VALUE) if err != nil { return res, err } From c52f8312e4641cb684cf9c206b91b89b5617a2ff Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 2 Nov 2024 03:21:38 +0300 Subject: [PATCH 75/86] Remove the dbmock and userdbmock --- internal/testutil/mocks/dbmock.go | 59 --------------------------- internal/testutil/mocks/userdbmock.go | 24 ----------- 2 files changed, 83 deletions(-) delete mode 100644 internal/testutil/mocks/dbmock.go delete mode 100644 internal/testutil/mocks/userdbmock.go diff --git a/internal/testutil/mocks/dbmock.go b/internal/testutil/mocks/dbmock.go deleted file mode 100644 index 0b40eab..0000000 --- a/internal/testutil/mocks/dbmock.go +++ /dev/null @@ -1,59 +0,0 @@ -package mocks - -import ( - "context" - - "git.defalsify.org/vise.git/lang" - "github.com/stretchr/testify/mock" -) - -type MockDb struct { - mock.Mock -} - -func (m *MockDb) SetPrefix(prefix uint8) { - m.Called(prefix) -} - -func (m *MockDb) Prefix() uint8 { - args := m.Called() - return args.Get(0).(uint8) -} - -func (m *MockDb) Safe() bool { - args := m.Called() - return args.Get(0).(bool) -} - -func (m *MockDb) SetLanguage(language *lang.Language) { - m.Called(language) -} - -func (m *MockDb) SetLock(uint8, bool) error { - args := m.Called() - return args.Error(0) -} - -func (m *MockDb) Connect(ctx context.Context, connectionStr string) error { - args := m.Called(ctx, connectionStr) - return args.Error(0) -} - -func (m *MockDb) SetSession(sessionId string) { - m.Called(sessionId) -} - -func (m *MockDb) Put(ctx context.Context, key, value []byte) error { - args := m.Called(ctx, key, value) - return args.Error(0) -} - -func (m *MockDb) Get(ctx context.Context, key []byte) ([]byte, error) { - args := m.Called(ctx, key) - return nil, args.Error(0) -} - -func (m *MockDb) Close() error { - args := m.Called(nil) - return args.Error(0) -} diff --git a/internal/testutil/mocks/userdbmock.go b/internal/testutil/mocks/userdbmock.go deleted file mode 100644 index ff3f18d..0000000 --- a/internal/testutil/mocks/userdbmock.go +++ /dev/null @@ -1,24 +0,0 @@ -package mocks - -import ( - "context" - - "git.defalsify.org/vise.git/db" - "git.grassecon.net/urdt/ussd/internal/utils" - "github.com/stretchr/testify/mock" -) - -type MockUserDataStore struct { - db.Db - mock.Mock -} - -func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ utils.DataTyp) ([]byte, error) { - args := m.Called(ctx, sessionId, typ) - return args.Get(0).([]byte), args.Error(1) -} - -func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ utils.DataTyp, value []byte) error { - args := m.Called(ctx, sessionId, typ, value) - return args.Error(0) -} From 476a69fe1b7fcd67728a9eaf5f5526b4010d4a1e Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Sat, 2 Nov 2024 03:22:33 +0300 Subject: [PATCH 76/86] Update menuhandler tests to use the memdb instead of dbmocks --- internal/handlers/ussd/menuhandler_test.go | 1185 +++++++++----------- 1 file changed, 510 insertions(+), 675 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 6f70108..48eb81a 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -7,10 +7,7 @@ import ( "log" "path" "testing" - "time" - "git.defalsify.org/vise.git/asm" - "git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/lang" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" @@ -20,7 +17,6 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/common" "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -36,15 +32,46 @@ var ( flagsPath = path.Join(baseDir, "services", "registration", "pp.csv") ) +// InitializeTestStore sets up and returns an in-memory database and store. +func InitializeTestStore(t *testing.T) (context.Context, *utils.UserDataStore) { + ctx := context.Background() + + // Initialize memDb + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + require.NoError(t, err, "Failed to connect to memDb") + + // Create UserDataStore with memDb + store := &utils.UserDataStore{Db: db} + + t.Cleanup(func() { + db.Close() // Ensure the DB is closed after each test + }) + + return ctx, store +} + +func InitializeTestSubPrefixDb(t *testing.T, ctx context.Context) *storage.SubPrefixDb { + db := memdb.NewMemDb() + err := db.Connect(ctx, "") + if err != nil { + t.Fatal(err) + } + spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + + return spdb +} + func TestNewHandlers(t *testing.T) { + _, store := InitializeTestStore(t) + fm, err := NewFlagManager(flagsPath) accountService := testservice.TestAccountService{} if err != nil { t.Logf(err.Error()) } t.Run("Valid UserDataStore", func(t *testing.T) { - mockStore := &mocks.MockUserDataStore{} - handlers, err := NewHandlers(fm.parser, mockStore, &accountService) + handlers, err := NewHandlers(fm.parser, store, &accountService) if err != nil { t.Fatalf("expected no error, got %v", err) } @@ -58,10 +85,7 @@ func TestNewHandlers(t *testing.T) { // Test case for nil userdataStore t.Run("Nil UserDataStore", func(t *testing.T) { - appFlags := &asm.FlagParser{} - - handlers, err := NewHandlers(appFlags, nil, &accountService) - + handlers, err := NewHandlers(fm.parser, nil, &accountService) if err == nil { t.Fatal("expected an error, got none") } @@ -75,19 +99,19 @@ func TestNewHandlers(t *testing.T) { } func TestCreateAccount(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - // Create required mocks + flag_account_created, err := fm.GetFlag("flag_account_created") if err != nil { t.Logf(err.Error()) } - // Define session ID and mock data - sessionId := "session123" - notFoundErr := db.ErrNotFound{} - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -111,47 +135,24 @@ func TestCreateAccount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + mockAccountService := new(mocks.MockAccountService) - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - - // Create a Handlers instance with the mock data store h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } - publicKey := tt.serverResponse.Result["publicKey"].(string) - data := map[utils.DataTyp]string{ - utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), - utils.DATA_PUBLIC_KEY: publicKey, - } - - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) - mockCreateAccountService.On("CreateAccount").Return(tt.serverResponse, nil) - - for key, value := range data { - mockDataStore.On("WriteEntry", ctx, sessionId, key, []byte(value)).Return(nil) - } - publicKeyNormalized, err := common.NormalizeHex(publicKey) - if err != nil { - t.Fatal(err) - } - - mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil) + mockAccountService.On("CreateAccount").Return(tt.serverResponse, nil) // Call the method you want to test - res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) + res, err := h.CreateAccount(ctx, "create_account", []byte("")) // Assert that no errors occurred assert.NoError(t, err) // Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) }) } } @@ -176,23 +177,28 @@ func TestWithPersister_PanicWhenAlreadySet(t *testing.T) { } func TestSaveFirstname(t *testing.T) { - // Create new mocks - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) - fm, err := NewFlagManager(flagsPath) + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) // Define test data - sessionId := "session123" firstName := "John" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil) + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)); err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, flagManager: fm.parser, st: mockState, } @@ -204,28 +210,34 @@ func TestSaveFirstname(t *testing.T) { assert.NoError(t, err) assert.Equal(t, resource.Result{}, res) - // Assert all expectations were met - mockStore.AssertExpectations(t) + // Verify that the DATA_FIRST_NAME entry has been updated with the temporary value + storedFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_FIRST_NAME) + assert.Equal(t, firstName, string(storedFirstName)) } func TestSaveFamilyname(t *testing.T) { - // Create a new instance of UserDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) - fm, err := NewFlagManager(flagsPath) + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) // Define test data - sessionId := "session123" familyName := "Doeee" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil) + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)); err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, st: mockState, flagManager: fm.parser, } @@ -237,25 +249,213 @@ func TestSaveFamilyname(t *testing.T) { assert.NoError(t, err) assert.Equal(t, resource.Result{}, res) - // Assert all expectations were met - mockStore.AssertExpectations(t) + // Verify that the DATA_FAMILY_NAME entry has been updated with the temporary value + storedFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_FAMILY_NAME) + assert.Equal(t, familyName, string(storedFamilyName)) +} + +func TestSaveYoB(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + yob := "1980" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveYob(ctx, "save_yob", []byte(yob)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_YOB entry has been updated with the temporary value + storedYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_YOB) + assert.Equal(t, yob, string(storedYob)) +} + +func TestSaveLocation(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + location := "Kilifi" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveLocation(ctx, "save_location", []byte(location)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_LOCATION entry has been updated with the temporary value + storedLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_LOCATION) + assert.Equal(t, location, string(storedLocation)) +} + +func TestSaveOfferings(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test data + offerings := "Bananas" + + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)); err != nil { + t.Fatal(err) + } + + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + flagManager: fm.parser, + st: mockState, + } + + // Call the method + res, err := h.SaveOfferings(ctx, "save_offerings", []byte(offerings)) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_OFFERINGS entry has been updated with the temporary value + storedOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_OFFERINGS) + assert.Equal(t, offerings, string(storedOfferings)) +} + +func TestSaveGender(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + + flag_allow_update, _ := fm.GetFlag("flag_allow_update") + + // Set the flag in the State + mockState := state.NewState(16) + mockState.SetFlag(flag_allow_update) + + // Define test cases + tests := []struct { + name string + input []byte + expectedGender string + executingSymbol string + }{ + { + name: "Valid Male Input", + input: []byte("1"), + expectedGender: "male", + executingSymbol: "set_male", + }, + { + name: "Valid Female Input", + input: []byte("2"), + expectedGender: "female", + executingSymbol: "set_female", + }, + { + name: "Valid Unspecified Input", + input: []byte("3"), + executingSymbol: "set_unspecified", + expectedGender: "unspecified", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)); err != nil { + t.Fatal(err) + } + + mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) + // Create the Handlers instance with the mock store + h := &Handlers{ + userdataStore: store, + st: mockState, + flagManager: fm.parser, + } + + // Call the method + res, err := h.SaveGender(ctx, "save_gender", tt.input) + + // Assert results + assert.NoError(t, err) + assert.Equal(t, resource.Result{}, res) + + // Verify that the DATA_GENDER entry has been updated with the temporary value + storedGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_GENDER) + assert.Equal(t, tt.expectedGender, string(storedGender)) + }) + } } func TestSaveTemporaryPin(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) - mockStore := new(mocks.MockUserDataStore) if err != nil { log.Fatal(err) } + flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, - userdataStore: mockStore, + userdataStore: store, } - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Define test cases tests := []struct { @@ -281,10 +481,6 @@ func TestSaveTemporaryPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil) - // Call the method res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) @@ -293,205 +489,27 @@ func TestSaveTemporaryPin(t *testing.T) { } // Assert that the Result FlagSet has the required flags after language switch - assert.Equal(t, res, tt.expectedResult, "Flags should be equal to account created") - - }) - } -} - -func TestSaveYoB(t *testing.T) { - // Create new instances - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - yob := "1980" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveYob(ctx, "save_yob", []byte(yob)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveLocation(t *testing.T) { - // Create a new instance of MockMyDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - yob := "Kilifi" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveLocation(ctx, "save_location", []byte(yob)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveOfferings(t *testing.T) { - // Create a new instance of MockUserDataStore - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, err := NewFlagManager(flagsPath) - - // Define test data - sessionId := "session123" - offerings := "Bananas" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - res, err := h.SaveOfferings(ctx, "save_offerings", []byte(offerings)) - - // Assert results - assert.NoError(t, err) - assert.Equal(t, resource.Result{}, res) - - // Assert all expectations were met - mockStore.AssertExpectations(t) -} - -func TestSaveGender(t *testing.T) { - // Create a new mock instances - mockStore := new(mocks.MockUserDataStore) - mockState := state.NewState(16) - - fm, _ := NewFlagManager(flagsPath) - - // Define the session ID and context - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Define test cases - tests := []struct { - name string - input []byte - expectedGender string - expectCall bool - executingSymbol string - }{ - { - name: "Valid Male Input", - input: []byte("1"), - expectedGender: "male", - executingSymbol: "set_male", - expectCall: true, - }, - { - name: "Valid Female Input", - input: []byte("2"), - expectedGender: "female", - executingSymbol: "set_female", - expectCall: true, - }, - { - name: "Valid Unspecified Input", - input: []byte("3"), - executingSymbol: "set_unspecified", - expectedGender: "unspecified", - expectCall: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Set up expectations for the mock database - if tt.expectCall { - expectedKey := utils.DATA_TEMPORARY_VALUE - mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) - } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil) - } - mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - st: mockState, - flagManager: fm.parser, - } - - // Call the method - _, err := h.SaveGender(ctx, "save_gender", tt.input) - - // Assert no error - assert.NoError(t, err) - - // Verify expectations - if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)) - } + assert.Equal(t, res, tt.expectedResult, "Result should match expected result") }) } } func TestCheckIdentifier(t *testing.T) { - // Create a new instance of MockMyDataStore - mockStore := new(mocks.MockUserDataStore) - - // Define the session ID and context sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) // Define test cases tests := []struct { name string - mockPublicKey []byte + publicKey []byte mockErr error expectedContent string expectError bool }{ { name: "Saved public Key", - mockPublicKey: []byte("0xa8363"), + publicKey: []byte("0xa8363"), mockErr: nil, expectedContent: "0xa8363", expectError: false, @@ -500,39 +518,33 @@ func TestCheckIdentifier(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Set up expectations for the mock database - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.mockPublicKey, tt.mockErr) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(tt.publicKey)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, } // Call the method res, err := h.CheckIdentifier(ctx, "check_identifier", nil) // Assert results - assert.NoError(t, err) assert.Equal(t, tt.expectedContent, res.Content) - - // Verify expectations - mockStore.AssertExpectations(t) }) } } func TestGetSender(t *testing.T) { - mockStore := new(mocks.MockUserDataStore) + sessionId := "session123" + ctx, _ := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) - // Define test data - sessionId := "254712345678" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - // Create the Handlers instance with the mock store - h := &Handlers{ - userdataStore: mockStore, - } + // Create the Handlers instance + h := &Handlers{} // Call the method res, _ := h.GetSender(ctx, "get_sender", []byte("")) @@ -542,21 +554,27 @@ func TestGetSender(t *testing.T) { } func TestGetAmount(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) // Define test data - sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) amount := "0.03" activeSym := "SRF" - // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(activeSym), nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return([]byte(amount), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(amount)) + if err != nil { + t.Fatal(err) + } + + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(activeSym)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, } // Call the method @@ -566,31 +584,30 @@ func TestGetAmount(t *testing.T) { //Assert that the retrieved amount is what was set as the content assert.Equal(t, formattedAmount, res.Content) - } func TestGetRecipient(t *testing.T) { - mockStore := new(mocks.MockUserDataStore) - - // Define test data sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + recepient := "0xcasgatweksalw1018221" - // Set up the expected behavior of the mock - mockStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return([]byte(recepient), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(recepient)) + if err != nil { + t.Fatal(err) + } // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockStore, + userdataStore: store, } // Call the method - res, _ := h.GetRecipient(ctx, "get_recipient", []byte("Getting recipient...")) + res, _ := h.GetRecipient(ctx, "get_recipient", []byte("")) //Assert that the retrieved recepient is what was set as the content assert.Equal(t, recepient, res.Content) - } func TestGetFlag(t *testing.T) { @@ -608,12 +625,11 @@ func TestGetFlag(t *testing.T) { } func TestSetLanguage(t *testing.T) { - // Create a new instance of the Flag Manager fm, err := NewFlagManager(flagsPath) - if err != nil { log.Fatal(err) } + // Define test cases tests := []struct { name string @@ -652,25 +668,24 @@ func TestSetLanguage(t *testing.T) { // Call the method res, err := h.SetLanguage(context.Background(), "set_language", nil) - if err != nil { t.Error(err) } // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should match expected result") - }) } } + func TestResetAllowUpdate(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update") - if err != nil { log.Fatal(err) } + + flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update") + // Define test cases tests := []struct { name string @@ -688,7 +703,6 @@ func TestResetAllowUpdate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -696,13 +710,12 @@ func TestResetAllowUpdate(t *testing.T) { // Call the method res, err := h.ResetAllowUpdate(context.Background(), "reset_allow update", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Flags should be equal to account created") - }) } } @@ -740,25 +753,24 @@ func TestResetAccountAuthorized(t *testing.T) { // Call the method res, err := h.ResetAccountAuthorized(context.Background(), "reset_account_authorized", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestIncorrectPinReset(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") - if err != nil { log.Fatal(err) } + + flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") + // Define test cases tests := []struct { name string @@ -776,7 +788,6 @@ func TestIncorrectPinReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -784,25 +795,24 @@ func TestIncorrectPinReset(t *testing.T) { // Call the method res, err := h.ResetIncorrectPin(context.Background(), "reset_incorrect_pin", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestResetIncorrectYob(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") - if err != nil { log.Fatal(err) } + + flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") + // Define test cases tests := []struct { name string @@ -820,7 +830,6 @@ func TestResetIncorrectYob(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create the Handlers instance with the mock flag manager h := &Handlers{ flagManager: fm.parser, @@ -828,43 +837,39 @@ func TestResetIncorrectYob(t *testing.T) { // Call the method res, err := h.ResetIncorrectYob(context.Background(), "reset_incorrect_yob", tt.input) - if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestAuthorize(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - //expectedResult := resource.Result{} + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin") flag_account_authorized, _ := fm.GetFlag("flag_account_authorized") flag_allow_update, _ := fm.GetFlag("flag_allow_update") - //Assuming 1234 is the correct account pin + + // Set 1234 is the correct account pin accountPIN := "1234" - // Define session ID and mock data - sessionId := "session123" - typ := utils.DATA_ACCOUNT_PIN - h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -899,14 +904,13 @@ func TestAuthorize(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create context with session ID ctx := context.WithValue(context.Background(), "SessionId", sessionId) - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(accountPIN), nil) - - // Create a Handlers instance with the mock data store + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, err := h.Authorize(ctx, "authorize", []byte(tt.input)) @@ -916,33 +920,25 @@ func TestAuthorize(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestVerifyYob(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } sessionId := "session123" // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format") ctx := context.WithValue(context.Background(), "SessionId", sessionId) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -977,7 +973,6 @@ func TestVerifyYob(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Call the method under test res, err := h.VerifyYob(ctx, "verify_yob", []byte(tt.input)) @@ -986,37 +981,31 @@ func TestVerifyYob(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } func TestVerifyCreatePin(t *testing.T) { - fm, err := NewFlagManager(flagsPath) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - sessionId := "session123" // Create required mocks - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") flag_pin_set, _ := fm.parser.GetFlag("flag_pin_set") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - //Assuming this was the first set PIN to verify against - firstSetPin := "1234" h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, st: mockState, } @@ -1043,16 +1032,12 @@ func TestVerifyCreatePin(t *testing.T) { }, } - typ := utils.DATA_TEMPORARY_VALUE - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte(firstSetPin), nil) - - // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(firstSetPin)).Return(nil) + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte("1234")) + if err != nil { + t.Fatal(err) + } // Call the method under test res, err := h.VerifyCreatePin(ctx, "verify_create_pin", []byte(tt.input)) @@ -1062,36 +1047,32 @@ func TestVerifyCreatePin(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } func TestCheckAccountStatus(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - sessionId := "session123" flag_account_success, _ := fm.GetFlag("flag_account_success") flag_account_pending, _ := fm.GetFlag("flag_account_pending") flag_api_error, _ := fm.GetFlag("flag_api_call_error") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - tests := []struct { name string - input []byte + publicKey []byte serverResponse *api.OKResponse - response *models.TrackStatusResponse expectedResult resource.Result }{ { - name: "Test when account is on the Sarafu network", - input: []byte("TrackingId1234"), + name: "Test when account is on the Sarafu network", + publicKey: []byte("TrackingId1234"), serverResponse: &api.OKResponse{ Ok: true, Description: "Account creation succeeded", @@ -1099,54 +1080,14 @@ func TestCheckAccountStatus(t *testing.T) { "active": true, }, }, - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_success}, FlagReset: []uint32{flag_api_error, flag_account_pending}, }, }, { - name: "Test when the account is not yet on the sarafu network", - input: []byte("TrackingId1234"), - response: &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - }, + name: "Test when the account is not yet on the sarafu network", + publicKey: []byte("TrackingId1234"), serverResponse: &api.OKResponse{ Ok: true, Description: "Account creation succeeded", @@ -1162,59 +1103,51 @@ func TestCheckAccountStatus(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } - status := tt.response.Result.Transaction.Status - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.input, nil) + err = store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(tt.publicKey)) + if err != nil { + t.Fatal(err) + } - mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) - mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() + mockAccountService.On("TrackAccountStatus", string(tt.publicKey)).Return(tt.serverResponse, nil) // Call the method under test - res, _ := h.CheckAccountStatus(ctx, "check_account_status", tt.input) + res, _ := h.CheckAccountStatus(ctx, "check_account_status", []byte("")) // Assert that no errors occurred assert.NoError(t, err) //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestTransactionReset(t *testing.T) { - fm, err := NewFlagManager(flagsPath) + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } + flag_invalid_recipient, _ := fm.GetFlag("flag_invalid_recipient") flag_invalid_recipient_with_invite, _ := fm.GetFlag("flag_invalid_recipient_with_invite") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) - - sessionId := "session123" - - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1233,9 +1166,6 @@ func TestTransactionReset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, []byte("")).Return(nil) - // Call the method under test res, _ := h.TransactionReset(ctx, "transaction_reset", tt.input) @@ -1244,40 +1174,32 @@ func TestTransactionReset(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } -func TestResetInvalidAmount(t *testing.T) { +func TestResetTransactionAmount(t *testing.T) { sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { name string - input []byte - status string expectedResult resource.Result }{ { @@ -1289,43 +1211,34 @@ func TestResetInvalidAmount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, []byte("")).Return(nil) - // Call the method under test - res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", tt.input) + res, _ := h.ResetTransactionAmount(ctx, "transaction_reset_amount", []byte("")) // Assert that no errors occurred assert.NoError(t, err) //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } - } func TestInitiateTransaction(t *testing.T) { sessionId := "254712345678" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } - account_authorized_flag, err := fm.parser.GetFlag("flag_account_authorized") + account_authorized_flag, _ := fm.parser.GetFlag("flag_account_authorized") - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } @@ -1351,10 +1264,18 @@ func TestInitiateTransaction(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Define expected interactions with the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_AMOUNT).Return(tt.Amount, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_RECIPIENT).Return(tt.Recipient, nil) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return(tt.ActiveSym, nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(tt.Amount)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(tt.Recipient)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(tt.ActiveSym)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, _ := h.InitiateTransaction(ctx, "transaction_reset_amount", tt.input) @@ -1364,31 +1285,25 @@ func TestInitiateTransaction(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) }) } } func TestQuit(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } flag_account_authorized, _ := fm.parser.GetFlag("flag_account_authorized") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1417,13 +1332,10 @@ func TestQuit(t *testing.T) { //Assert that the account created flag has been set to the result assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - }) } } + func TestIsValidPIN(t *testing.T) { tests := []struct { name string @@ -1479,21 +1391,22 @@ func TestIsValidPIN(t *testing.T) { func TestValidateAmount(t *testing.T) { fm, err := NewFlagManager(flagsPath) - if err != nil { t.Logf(err.Error()) } - flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount") + + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, flagManager: fm.parser, } tests := []struct { @@ -1533,11 +1446,10 @@ func TestValidateAmount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Mock behavior for active balance retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL).Return(tt.activeBal, nil) - - // Mock behavior for storing the amount (if valid) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil).Maybe() + err := store.WriteEntry(ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(tt.activeBal)) + if err != nil { + t.Fatal(err) + } // Call the method under test res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input) @@ -1547,26 +1459,22 @@ func TestValidateAmount(t *testing.T) { // Assert the result matches the expected result assert.Equal(t, tt.expectedResult, res, "Expected result should match actual result") - - // Assert all expectations were met - mockDataStore.AssertExpectations(t) }) } } func TestValidateRecipient(t *testing.T) { fm, err := NewFlagManager(flagsPath) - - flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient") - mockDataStore := new(mocks.MockUserDataStore) - - sessionId := "session123" - - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - if err != nil { log.Fatal(err) } + + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient") + // Define test cases tests := []struct { name string @@ -1590,13 +1498,10 @@ func TestValidateRecipient(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_RECIPIENT, tt.input).Return(nil) - - // Create the Handlers instance with the mock flag manager + // Create the Handlers instance h := &Handlers{ flagManager: fm.parser, - userdataStore: mockDataStore, + userdataStore: store, } // Call the method @@ -1605,14 +1510,16 @@ func TestValidateRecipient(t *testing.T) { if err != nil { t.Error(err) } + // Assert that the Result FlagSet has the required flags after language switch assert.Equal(t, res, tt.expectedResult, "Result should contain flag(s) that have been reset") - }) } } func TestCheckBalance(t *testing.T) { + ctx, store := InitializeTestStore(t) + tests := []struct { name string sessionId string @@ -1624,7 +1531,7 @@ func TestCheckBalance(t *testing.T) { }{ { name: "User with active sym", - sessionId: "session456", + sessionId: "session123", publicKey: "0X98765432109", activeSym: "ETH", activeBal: "1.5", @@ -1635,18 +1542,22 @@ func TestCheckBalance(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - ctx := context.WithValue(context.Background(), "SessionId", tt.sessionId) + ctx := context.WithValue(ctx, "SessionId", tt.sessionId) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, } - // Mock for user with active sym - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(tt.activeSym), nil) - mockDataStore.On("ReadEntry", ctx, tt.sessionId, utils.DATA_ACTIVE_BAL).Return([]byte(tt.activeBal), nil) + err := store.WriteEntry(ctx, tt.sessionId, utils.DATA_ACTIVE_SYM, []byte(tt.activeSym)) + if err != nil { + t.Fatal(err) + } + err = store.WriteEntry(ctx, tt.sessionId, utils.DATA_ACTIVE_BAL, []byte(tt.activeBal)) + if err != nil { + t.Fatal(err) + } res, err := h.CheckBalance(ctx, "check_balance", []byte("")) @@ -1657,23 +1568,21 @@ func TestCheckBalance(t *testing.T) { assert.Equal(t, tt.expectedResult, res, "Result should match expected output") } - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) }) } } func TestGetProfile(t *testing.T) { - sessionId := "session123" + ctx, store := InitializeTestStore(t) - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) h := &Handlers{ - userdataStore: mockDataStore, - accountService: mockCreateAccountService, + userdataStore: store, + accountService: mockAccountService, st: mockState, } @@ -1697,7 +1606,7 @@ func TestGetProfile(t *testing.T) { }, }, { - name: "Test with with profile information in swa ", + name: "Test with with profile information in swa", keys: []utils.DataTyp{utils.DATA_FAMILY_NAME, utils.DATA_FIRST_NAME, utils.DATA_GENDER, utils.DATA_OFFERINGS, utils.DATA_LOCATION, utils.DATA_YOB}, profileInfo: []string{"Doee", "John", "Male", "Bananas", "Kilifi", "1976"}, languageCode: "swa", @@ -1723,22 +1632,21 @@ func TestGetProfile(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "Language", lang.Language{ Code: tt.languageCode, }) for index, key := range tt.keys { - mockDataStore.On("ReadEntry", ctx, sessionId, key).Return([]byte(tt.profileInfo[index]), nil).Maybe() + err := store.WriteEntry(ctx, sessionId, key, []byte(tt.profileInfo[index])) + if err != nil { + t.Fatal(err) + } } res, _ := h.GetProfileInfo(ctx, "get_profile_info", []byte("")) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.result, "Result should contain profile information served back to user") - }) } } @@ -1749,12 +1657,10 @@ func TestVerifyNewPin(t *testing.T) { fm, _ := NewFlagManager(flagsPath) flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, flagManager: fm.parser, - accountService: mockCreateAccountService, + accountService: mockAccountService, } ctx := context.WithValue(context.Background(), "SessionId", sessionId) @@ -1777,44 +1683,32 @@ func TestVerifyNewPin(t *testing.T) { FlagReset: []uint32{flag_valid_pin}, }, }, - { - name: "Test with invalid pin", - input: []byte("12345"), - expectedResult: resource.Result{ - FlagReset: []uint32{flag_valid_pin}, - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - //Call the function under test res, _ := h.VerifyNewPin(ctx, "verify_new_pin", tt.input) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") - }) } - } func TestConfirmPin(t *testing.T) { sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, _ := NewFlagManager(flagsPath) flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, - accountService: mockCreateAccountService, + accountService: mockAccountService, } - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -1834,16 +1728,14 @@ func TestConfirmPin(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Set up the expected behavior of the mock - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil) - - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.temporarypin)) + if err != nil { + t.Fatal(err) + } //Call the function under test res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") @@ -1861,7 +1753,14 @@ func TestFetchCustodialBalances(t *testing.T) { // Define test data sessionId := "session123" publicKey := "0X13242618721" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + err = store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } tests := []struct { name string @@ -1903,50 +1802,39 @@ func TestFetchCustodialBalances(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - - mockDataStore := new(mocks.MockUserDataStore) - mockCreateAccountService := new(mocks.MockAccountService) + mockAccountService := new(mocks.MockAccountService) mockState := state.NewState(16) - // Create the Handlers instance with the mock store h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, st: mockState, - accountService: mockCreateAccountService, + accountService: mockAccountService, } // Set up the expected behavior of the mock - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) - mockCreateAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) + mockAccountService.On("CheckBalance", string(publicKey)).Return(tt.balanceResonse, nil) // Call the method res, _ := h.FetchCustodialBalances(ctx, "fetch_custodial_balances", []byte("")) - // Assert that expectations were met - mockDataStore.AssertExpectations(t) - //Assert that the result set to content is what was expected - assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") - + assert.Equal(t, res, tt.expectedResult, "Result should match expected result") }) } } func TestSetDefaultVoucher(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } - flag_no_active_voucher, err := fm.GetFlag("flag_no_active_voucher") - if err != nil { - t.Logf(err.Error()) - } - // Define session ID and mock data - sessionId := "session123" + publicKey := "0X13242618721" - notFoundErr := db.ErrNotFound{} - ctx := context.WithValue(context.Background(), "SessionId", sessionId) tests := []struct { name string @@ -1954,7 +1842,7 @@ func TestSetDefaultVoucher(t *testing.T) { expectedResult resource.Result }{ { - name: "Test set default voucher when no active voucher exists", + name: "Test set default voucher when no active voucher is set", vouchersResp: &models.VoucherHoldingResponse{ Ok: true, Description: "Vouchers fetched successfully", @@ -1971,77 +1859,55 @@ func TestSetDefaultVoucher(t *testing.T) { }, expectedResult: resource.Result{}, }, - { - name: "Test no vouchers available", - vouchersResp: &models.VoucherHoldingResponse{ - Ok: true, - Description: "No vouchers available", - Result: models.VoucherResult{ - Holdings: []dataserviceapi.TokenHoldings{}, - }, - }, - expectedResult: resource.Result{ - FlagSet: []uint32{flag_no_active_voucher}, - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, flagManager: fm.parser, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM).Return([]byte(""), notFoundErr) - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) - if len(tt.vouchersResp.Result.Holdings) > 0 { - firstVoucher := tt.vouchersResp.Result.Holdings[0] - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_SYM, []byte(firstVoucher.TokenSymbol)).Return(nil) - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACTIVE_BAL, []byte(firstVoucher.Balance)).Return(nil) - } - - res, err := h.SetDefaultVoucher(ctx, "set_default_voucher", []byte("some-input")) + res, err := h.SetDefaultVoucher(ctx, "set_default_voucher", []byte("")) assert.NoError(t, err) assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) }) } } func TestCheckVouchers(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) mockAccountService := new(mocks.MockAccountService) - sessionId := "session123" publicKey := "0X13242618721" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, accountService: mockAccountService, prefixDb: spdb, } - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return([]byte(publicKey), nil) + err := store.WriteEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } mockVouchersResponse := &models.VoucherHoldingResponse{} mockVouchersResponse.Result.Holdings = []dataserviceapi.TokenHoldings{ @@ -2065,7 +1931,6 @@ func TestCheckVouchers(t *testing.T) { // assert that the data is stored correctly assert.Equal(t, expectedSym, voucherData) - mockDataStore.AssertExpectations(t) mockAccountService.AssertExpectations(t) } @@ -2073,12 +1938,7 @@ func TestGetVoucherList(t *testing.T) { sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err := db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ prefixDb: spdb, @@ -2087,7 +1947,7 @@ func TestGetVoucherList(t *testing.T) { expectedSym := []byte("1:SRF\n2:MILO") // Put voucher sym data from the store - err = spdb.Put(ctx, []byte("sym"), expectedSym) + err := spdb.Put(ctx, []byte("sym"), expectedSym) if err != nil { t.Fatal(err) } @@ -2103,20 +1963,15 @@ func TestViewVoucher(t *testing.T) { if err != nil { t.Logf(err.Error()) } - mockDataStore := new(mocks.MockUserDataStore) - + ctx, store := InitializeTestStore(t) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) - db := memdb.NewMemDb() - err = db.Connect(ctx, "") - if err != nil { - t.Fatal(err) - } - spdb := storage.NewSubPrefixDb(db, []byte("vouchers")) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + spdb := InitializeTestSubPrefixDb(t, ctx) h := &Handlers{ - userdataStore: mockDataStore, + userdataStore: store, flagManager: fm.parser, prefixDb: spdb, } @@ -2137,23 +1992,20 @@ func TestViewVoucher(t *testing.T) { } } - // Set up expectations for mockDataStore - expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce") - - mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil) - res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) - assert.Contains(t, res.Content, "SRF\n100") - - mockDataStore.AssertExpectations(t) + assert.Equal(t, res.Content, "SRF\n100") } func TestSetVoucher(t *testing.T) { - mockDataStore := new(mocks.MockUserDataStore) - + ctx, store := InitializeTestStore(t) sessionId := "session123" - ctx := context.WithValue(context.Background(), "SessionId", sessionId) + + ctx = context.WithValue(ctx, "SessionId", sessionId) + + h := &Handlers{ + userdataStore: store, + } // Define the temporary voucher data tempData := &dataserviceapi.TokenHoldings{ @@ -2163,33 +2015,16 @@ func TestSetVoucher(t *testing.T) { ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", } - expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9") + expectedData := fmt.Sprintf("%s,%s,%s,%s", tempData.TokenSymbol, tempData.Balance, tempData.TokenDecimals, tempData.ContractAddress) - // Define the expected active entries - activeEntries := map[utils.DataTyp][]byte{ - utils.DATA_ACTIVE_SYM: []byte(tempData.TokenSymbol), - utils.DATA_ACTIVE_BAL: []byte(tempData.Balance), - utils.DATA_ACTIVE_DECIMAL: []byte(tempData.TokenDecimals), - utils.DATA_ACTIVE_ADDRESS: []byte(tempData.ContractAddress), + // store the expectedData + if err := store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)); err != nil { + t.Fatal(err) } - // Mocking ReadEntry calls for temporary data retrieval - mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil) - - // Mocking WriteEntry calls for setting active data - for key, value := range activeEntries { - mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil) - } - - h := &Handlers{ - userdataStore: mockDataStore, - } - - res, err := h.SetVoucher(ctx, "someSym", []byte{}) + res, err := h.SetVoucher(ctx, "set_voucher", []byte{}) assert.NoError(t, err) assert.Equal(t, string(tempData.TokenSymbol), res.Content) - - mockDataStore.AssertExpectations(t) } From e29a24b376cff982367fe2c00470ee1af8eea5cd Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 15:46:46 +0000 Subject: [PATCH 77/86] Add missing models files --- common/hex.go | 13 +++++++++++++ internal/handlers/handlerservice.go | 1 + internal/handlers/ussd/menuhandler.go | 20 ++++++++++---------- internal/models/tokenresponse.go | 18 ++++++++++++++++++ internal/models/vouchersresponse.go | 14 ++++++++++++++ 5 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 internal/models/tokenresponse.go create mode 100644 internal/models/vouchersresponse.go diff --git a/common/hex.go b/common/hex.go index f5aa7ed..971ecf1 100644 --- a/common/hex.go +++ b/common/hex.go @@ -2,6 +2,7 @@ package common import ( "encoding/hex" + "strings" ) func NormalizeHex(s string) (string, error) { @@ -16,3 +17,15 @@ func NormalizeHex(s string) (string, error) { } return hex.EncodeToString(r), nil } + +func IsSameHex(left string, right string) bool { + bl, err := NormalizeHex(left) + if err != nil { + return false + } + br, err := NormalizeHex(left) + if err != nil { + return false + } + return strings.Compare(bl, br) == 0 +} diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 9afba13..7d8325c 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -10,6 +10,7 @@ import ( "git.defalsify.org/vise.git/resource" "git.grassecon.net/urdt/ussd/internal/handlers/ussd" + "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/remote" ) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dc77660..a7e9d88 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -233,11 +233,11 @@ func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byt return res, fmt.Errorf("missing session") } store := h.userdataStore - blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } @@ -307,12 +307,12 @@ func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } temporaryPin := string(input) - blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) + err = store.WriteEntry(ctx, string(blockedNumber), common.DATA_TEMPORARY_VALUE, []byte(temporaryPin)) if err != nil { return res, err } @@ -841,15 +841,15 @@ func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) if err != nil { return res, err } - temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_VALUE) + temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), common.DATA_TEMPORARY_VALUE) if err != nil { return res, err } - err = store.WriteEntry(ctx, string(blockedPhonenumber), utils.DATA_ACCOUNT_PIN, []byte(temporaryPin)) + err = store.WriteEntry(ctx, string(blockedPhonenumber), common.DATA_ACCOUNT_PIN, []byte(temporaryPin)) if err != nil { return res, nil } @@ -874,7 +874,7 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } blockedNumber := string(input) - _, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY) + _, err = store.ReadEntry(ctx, blockedNumber, common.DATA_PUBLIC_KEY) if !isValidPhoneNumber(blockedNumber) { res.FlagSet = append(res.FlagSet, flag_unregistered_number) return res, nil @@ -888,7 +888,7 @@ func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input return res, err } } - err = store.WriteEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) + err = store.WriteEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) if err != nil { return res, nil } @@ -1075,7 +1075,7 @@ func (h *Handlers) RetrieveBlockedNumber(ctx context.Context, sym string, input return res, fmt.Errorf("missing session") } store := h.userdataStore - blockedNumber, _ := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER) + blockedNumber, _ := store.ReadEntry(ctx, sessionId, common.DATA_BLOCKED_NUMBER) res.Content = string(blockedNumber) diff --git a/internal/models/tokenresponse.go b/internal/models/tokenresponse.go new file mode 100644 index 0000000..d243d93 --- /dev/null +++ b/internal/models/tokenresponse.go @@ -0,0 +1,18 @@ +package models + +type ApiResponse struct { + OK bool `json:"ok"` + Description string `json:"description"` + Result Result `json:"result"` +} + +type Result struct { + Holdings []Holding `json:"holdings"` +} + +type Holding struct { + ContractAddress string `json:"contractAddress"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + Balance string `json:"balance"` +} diff --git a/internal/models/vouchersresponse.go b/internal/models/vouchersresponse.go new file mode 100644 index 0000000..09b085d --- /dev/null +++ b/internal/models/vouchersresponse.go @@ -0,0 +1,14 @@ +package models + +import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" + +type VoucherHoldingResponse struct { + Ok bool `json:"ok"` + Description string `json:"description"` + Result VoucherResult `json:"result"` +} + +// VoucherResult holds the list of token holdings +type VoucherResult struct { + Holdings []dataserviceapi.TokenHoldings `json:"holdings"` +} From 14bc11f4bd87574526b453339e4b079967216b83 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 16:38:29 +0000 Subject: [PATCH 78/86] Add transaction getter --- common/db.go | 2 +- common/vouchers.go | 9 +++++++++ remote/accountservice.go | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/common/db.go b/common/db.go index 58fd3a1..06d9607 100644 --- a/common/db.go +++ b/common/db.go @@ -30,7 +30,7 @@ const ( DATA_PUBLIC_KEY_REVERSE DATA_ACTIVE_DECIMAL DATA_ACTIVE_ADDRESS - + DATA_TRANSACTIONS ) func typToBytes(typ DataTyp) []byte { diff --git a/common/vouchers.go b/common/vouchers.go index 9ca6277..cd76060 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -37,6 +37,15 @@ func ProcessVouchers(holdings []dataserviceapi.TokenHoldings) VoucherMetadata { return data } +//func StoreVouchers(db storage.PrefixDb, data VoucherMetadata) { +// value, err := db.Put(ctx, []byte(key)) +// if err != nil { +// return nil, fmt.Errorf("failed to get %s: %v", key, err) +// } +// data[key] = string(value) +// } +//} + // GetVoucherData retrieves and matches voucher data func GetVoucherData(ctx context.Context, db storage.PrefixDb, input string) (*dataserviceapi.TokenHoldings, error) { keys := []string{"sym", "bal", "deci", "addr"} diff --git a/remote/accountservice.go b/remote/accountservice.go index bc6a448..d0d7e9b 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -22,6 +22,7 @@ type AccountServiceInterface interface { CreateAccount(ctx context.Context) (*models.AccountResult, error) TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) + FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) } type AccountService struct { @@ -100,13 +101,18 @@ func (as *AccountService) CreateAccount(ctx context.Context) (*models.AccountRes return &r, nil } -// FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint +// FetchVouchers retrieves the token holdings for a given public key from the data indexer API endpoint // Parameters: // - publicKey: The public key associated with the account. func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) { var r []dataserviceapi.TokenHoldings - req, err := http.NewRequest("GET", config.VoucherHoldingsURL, nil) + ep, err := url.JoinPath(config.VoucherHoldingsURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) if err != nil { return nil, err } @@ -119,6 +125,32 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ( return r, nil } + +// FetchTransactions retrieves the last 10 transactions for a given public key from the data indexer API endpoint +// Parameters: +// - publicKey: The public key associated with the account. +func (as *AccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + var r []dataserviceapi.Last10TxResponse + + ep, err := url.JoinPath(config.VoucherTransfersURL, publicKey) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + + _, err = doDataRequest(ctx, req, r) + if err != nil { + return nil, err + } + + return r, nil +} + + func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { var okResponse api.OKResponse var errResponse api.ErrResponse From 3a8a5f40baa56612e8435387542bbd2fcf16368b Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 16:42:50 +0000 Subject: [PATCH 79/86] Add test service placeholders for fetchtransactions --- internal/testutil/mocks/servicemock.go | 5 +++++ internal/testutil/testservice/TestAccountService.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index bec48fd..78ee2b0 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -33,3 +33,8 @@ func (m *MockAccountService) FetchVouchers(ctx context.Context, publicKey string args := m.Called(publicKey) return args.Get(0).([]dataserviceapi.TokenHoldings), args.Error(1) } + +func (m *MockAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + args := m.Called(publicKey) + return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1) +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index a9a3085..3c104bd 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -42,3 +42,7 @@ func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey stri }, }, nil } + +func (tas *TestAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { + return []dataserviceapi.Last10TxResponse{}, nil +} From 1d77ad98dc6e4d7be4a3f63561815c06d07039b2 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 23:33:52 +0000 Subject: [PATCH 80/86] Expose subprefix db --- common/storage.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 common/storage.go diff --git a/common/storage.go b/common/storage.go new file mode 100644 index 0000000..62a8a06 --- /dev/null +++ b/common/storage.go @@ -0,0 +1,13 @@ +package common + +import ( + "git.defalsify.org/vise.git/db" +) + +func StoreToDb(store *UserDataStore, prefix []byte) db.Db { + innerStore := store.Db + if pfx != nil { + innerStore = NewSubPrefixDb(innerStore, pfx) + } + return innerStore +} From dae12ac4989e40f64a48930b5348288c85af8369 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 2 Nov 2024 23:41:08 +0000 Subject: [PATCH 81/86] Separate subprefix db export --- common/storage.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common/storage.go b/common/storage.go index 62a8a06..145382d 100644 --- a/common/storage.go +++ b/common/storage.go @@ -2,12 +2,14 @@ package common import ( "git.defalsify.org/vise.git/db" + + "git.grassecon.net/urdt/ussd/internal/storage" ) -func StoreToDb(store *UserDataStore, prefix []byte) db.Db { - innerStore := store.Db - if pfx != nil { - innerStore = NewSubPrefixDb(innerStore, pfx) - } - return innerStore +func StoreToDb(store *UserDataStore) db.Db { + return store.Db +} + +func StoreToPrefixDb(store *UserDataStore, pfx []byte) storage.PrefixDb { + return storage.NewSubPrefixDb(store.Db, pfx) } From a237b615f2ee3148146883e9267ac3c4f77f35e7 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 01:44:57 +0000 Subject: [PATCH 82/86] Export models package --- common/user_store.go | 1 + internal/handlers/ussd/menuhandler_test.go | 2 +- internal/testutil/mocks/servicemock.go | 2 +- internal/testutil/testservice/TestAccountService.go | 2 +- {internal/models => models}/accountresponse.go | 0 {internal/models => models}/balanceresponse.go | 0 {internal/models => models}/tokenresponse.go | 0 {internal/models => models}/trackstatusresponse.go | 0 {internal/models => models}/vouchersresponse.go | 0 remote/accountservice.go | 2 +- 10 files changed, 5 insertions(+), 4 deletions(-) rename {internal/models => models}/accountresponse.go (100%) rename {internal/models => models}/balanceresponse.go (100%) rename {internal/models => models}/tokenresponse.go (100%) rename {internal/models => models}/trackstatusresponse.go (100%) rename {internal/models => models}/vouchersresponse.go (100%) diff --git a/common/user_store.go b/common/user_store.go index 4b8409f..29796e2 100644 --- a/common/user_store.go +++ b/common/user_store.go @@ -25,6 +25,7 @@ func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ } // WriteEntry adds an entry to the userdata store. +// BUG: this uses sessionId twice func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error { store.SetPrefix(db.DATATYPE_USERDATA) store.SetSession(sessionId) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 86c905d..74e9f53 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -14,7 +14,7 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index 78ee2b0..a24e459 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -3,7 +3,7 @@ package mocks import ( "context" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/stretchr/testify/mock" ) diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 3c104bd..21f7a63 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) diff --git a/internal/models/accountresponse.go b/models/accountresponse.go similarity index 100% rename from internal/models/accountresponse.go rename to models/accountresponse.go diff --git a/internal/models/balanceresponse.go b/models/balanceresponse.go similarity index 100% rename from internal/models/balanceresponse.go rename to models/balanceresponse.go diff --git a/internal/models/tokenresponse.go b/models/tokenresponse.go similarity index 100% rename from internal/models/tokenresponse.go rename to models/tokenresponse.go diff --git a/internal/models/trackstatusresponse.go b/models/trackstatusresponse.go similarity index 100% rename from internal/models/trackstatusresponse.go rename to models/trackstatusresponse.go diff --git a/internal/models/vouchersresponse.go b/models/vouchersresponse.go similarity index 100% rename from internal/models/vouchersresponse.go rename to models/vouchersresponse.go diff --git a/remote/accountservice.go b/remote/accountservice.go index d0d7e9b..402add5 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -11,7 +11,7 @@ import ( dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" "github.com/grassrootseconomics/eth-custodial/pkg/api" "git.grassecon.net/urdt/ussd/config" - "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/models" ) var ( From 0506a8c452f1c5daab3383d4c3248a0b0780dbdf Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 14:34:26 +0000 Subject: [PATCH 83/86] Add voucherdata endpoint --- common/db.go | 6 ++++++ common/vouchers.go | 2 ++ config/config.go | 3 +++ models/vouchersresponse.go | 17 ++++++++++++----- remote/accountservice.go | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/common/db.go b/common/db.go index 06d9607..91891d9 100644 --- a/common/db.go +++ b/common/db.go @@ -2,6 +2,8 @@ package common import ( "encoding/binary" + + "git.defalsify.org/vise.git/logging" ) type DataTyp uint16 @@ -33,6 +35,10 @@ const ( DATA_TRANSACTIONS ) +var ( + logg = logging.NewVanilla().WithDomain("urdt-common") +) + func typToBytes(typ DataTyp) []byte { var b [2]byte binary.BigEndian.PutUint16(b[:], uint16(typ)) diff --git a/common/vouchers.go b/common/vouchers.go index cd76060..2fed043 100644 --- a/common/vouchers.go +++ b/common/vouchers.go @@ -84,6 +84,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol, decList := strings.Split(decimals, "\n") addrList := strings.Split(addresses, "\n") + logg.Tracef("found" , "symlist", symList, "syms", symbols, "input", input) for i, sym := range symList { parts := strings.SplitN(sym, ":", 2) @@ -136,6 +137,7 @@ func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId str // UpdateVoucherData sets the active voucher data and clears the temporary voucher data in the DataStore. func UpdateVoucherData(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error { + logg.TraceCtxf(ctx, "dtal", "data", data) // Active voucher data entries activeEntries := map[DataTyp][]byte{ DATA_ACTIVE_SYM: []byte(data.TokenSymbol), diff --git a/config/config.go b/config/config.go index a5c89a7..fbf518b 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,7 @@ const ( trackPath = "/api/v2/account/status" voucherHoldingsPathPrefix = "/api/v1/holdings" voucherTransfersPathPrefix = "/api/v1/transfers/last10" + voucherDataPathPrefix = "/api/v1/token" ) var ( @@ -29,6 +30,7 @@ var ( TrackURL string VoucherHoldingsURL string VoucherTransfersURL string + VoucherDataURL string ) func setBase() error { @@ -62,6 +64,7 @@ func LoadConfig() error { TrackURL, _ = url.JoinPath(custodialURLBase, trackPath) VoucherHoldingsURL, _ = url.JoinPath(dataURLBase, voucherHoldingsPathPrefix) VoucherTransfersURL, _ = url.JoinPath(dataURLBase, voucherTransfersPathPrefix) + VoucherDataURL, _ = url.JoinPath(dataURLBase, voucherDataPathPrefix) return nil } diff --git a/models/vouchersresponse.go b/models/vouchersresponse.go index 09b085d..8cf3ec6 100644 --- a/models/vouchersresponse.go +++ b/models/vouchersresponse.go @@ -2,13 +2,20 @@ package models import dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" -type VoucherHoldingResponse struct { - Ok bool `json:"ok"` - Description string `json:"description"` - Result VoucherResult `json:"result"` -} +//type VoucherHoldingResponse struct { +// Ok bool `json:"ok"` +// Description string `json:"description"` +// Result VoucherResult `json:"result"` +//} // VoucherResult holds the list of token holdings type VoucherResult struct { Holdings []dataserviceapi.TokenHoldings `json:"holdings"` } + +type VoucherDataResult struct { + TokenName string `json:"tokenName"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + SinkAddress string `json:"sinkAddress"` +} diff --git a/remote/accountservice.go b/remote/accountservice.go index 402add5..73052f6 100644 --- a/remote/accountservice.go +++ b/remote/accountservice.go @@ -23,6 +23,7 @@ type AccountServiceInterface interface { TrackAccountStatus(ctx context.Context, publicKey string) (*models.TrackStatusResult, error) FetchVouchers(ctx context.Context, publicKey string) ([]dataserviceapi.TokenHoldings, error) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) + VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) } type AccountService struct { @@ -151,6 +152,26 @@ func (as *AccountService) FetchTransactions(ctx context.Context, publicKey strin } +// VoucherData retrieves voucher metadata from the data indexer API endpoint. +// Parameters: +// - address: The voucher address. +func (as *AccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + var voucherDataResult models.VoucherDataResult + + ep, err := url.JoinPath(config.VoucherDataURL, address) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", ep, nil) + if err != nil { + return nil, err + } + + _, err = doCustodialRequest(ctx, req, &voucherDataResult) + return &voucherDataResult, err +} + func doRequest(ctx context.Context, req *http.Request, rcpt any) (*api.OKResponse, error) { var okResponse api.OKResponse var errResponse api.ErrResponse From 7189235bee57b4fc703c5d7a2f43f0b4a660c397 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 3 Nov 2024 15:14:17 +0000 Subject: [PATCH 84/86] Remove unused data type --- common/db.go | 1 - 1 file changed, 1 deletion(-) diff --git a/common/db.go b/common/db.go index 91891d9..1992476 100644 --- a/common/db.go +++ b/common/db.go @@ -25,7 +25,6 @@ const ( DATA_RECIPIENT DATA_AMOUNT DATA_TEMPORARY_VALUE - DATA_VOUCHER_LIST DATA_ACTIVE_SYM DATA_ACTIVE_BAL DATA_BLOCKED_NUMBER From 2c30ccc4058f821f7996442963defced49e4146e Mon Sep 17 00:00:00 2001 From: lash Date: Mon, 4 Nov 2024 02:23:30 +0000 Subject: [PATCH 85/86] Add voucherdata call to test accountservices --- common/storage.go | 39 ++++++++++++++++++- internal/testutil/mocks/servicemock.go | 5 +++ .../testservice/TestAccountService.go | 4 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/common/storage.go b/common/storage.go index 145382d..dff4774 100644 --- a/common/storage.go +++ b/common/storage.go @@ -1,8 +1,12 @@ package common import ( - "git.defalsify.org/vise.git/db" + "context" + "errors" + "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/persist" "git.grassecon.net/urdt/ussd/internal/storage" ) @@ -13,3 +17,36 @@ func StoreToDb(store *UserDataStore) db.Db { func StoreToPrefixDb(store *UserDataStore, pfx []byte) storage.PrefixDb { return storage.NewSubPrefixDb(store.Db, pfx) } + +type StorageServices interface { + GetPersister(ctx context.Context) (*persist.Persister, error) + GetUserdataDb(ctx context.Context) (db.Db, error) + GetResource(ctx context.Context) (resource.Resource, error) + EnsureDbDir() error +} + +type StorageService struct { + svc *storage.MenuStorageService +} + +func NewStorageService(dbDir string) *StorageService { + return &StorageService{ + svc: storage.NewMenuStorageService(dbDir, ""), + } +} + +func(ss *StorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { + return ss.svc.GetPersister(ctx) +} + +func(ss *StorageService) GetUserdataDb(ctx context.Context) (db.Db, error) { + return ss.svc.GetUserdataDb(ctx) +} + +func(ss *StorageService) GetResource(ctx context.Context) (resource.Resource, error) { + return nil, errors.New("not implemented") +} + +func(ss *StorageService) EnsureDbDir() error { + return ss.svc.EnsureDbDir() +} diff --git a/internal/testutil/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go index a24e459..76803ba 100644 --- a/internal/testutil/mocks/servicemock.go +++ b/internal/testutil/mocks/servicemock.go @@ -38,3 +38,8 @@ func (m *MockAccountService) FetchTransactions(ctx context.Context, publicKey st args := m.Called(publicKey) return args.Get(0).([]dataserviceapi.Last10TxResponse), args.Error(1) } + +func(m MockAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + args := m.Called(address) + return args.Get(0).(*models.VoucherDataResult), args.Error(1) +} diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go index 21f7a63..8752d6f 100644 --- a/internal/testutil/testservice/TestAccountService.go +++ b/internal/testutil/testservice/TestAccountService.go @@ -46,3 +46,7 @@ func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey stri func (tas *TestAccountService) FetchTransactions(ctx context.Context, publicKey string) ([]dataserviceapi.Last10TxResponse, error) { return []dataserviceapi.Last10TxResponse{}, nil } + +func(m TestAccountService) VoucherData(ctx context.Context, address string) (*models.VoucherDataResult, error) { + return &models.VoucherDataResult{}, nil +} From 88b50c5dd77852b2cd88097973162e1090cc2e89 Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Mon, 4 Nov 2024 15:52:03 +0300 Subject: [PATCH 86/86] Remove admin number defination in env example --- .env.example | 4 --- internal/handlers/ussd/menuhandler.go | 3 +-- internal/handlers/ussd/menuhandler_test.go | 31 +++++++++++----------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index 4d86f8b..ab370a7 100644 --- a/.env.example +++ b/.env.example @@ -16,7 +16,3 @@ CREATE_ACCOUNT_URL=http://localhost:5003/api/v2/account/create TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/ BALANCE_URL=https://custodial.sarafu.africa/api/account/status/ TRACK_URL=http://localhost:5003/api/v2/account/status - - -#numbers with privileges to reset others pin -ADMIN_NUMBERS=254051722XXX,255012221XXX \ No newline at end of file diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index a7e9d88..6c1917d 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -20,8 +20,8 @@ import ( "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" "git.grassecon.net/urdt/ussd/common" - "git.grassecon.net/urdt/ussd/remote" "git.grassecon.net/urdt/ussd/internal/utils" + "git.grassecon.net/urdt/ussd/remote" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -1390,7 +1390,6 @@ func (h *Handlers) SetVoucher(ctx context.Context, sym string, input []byte) (re return res, fmt.Errorf("missing session") } - // Get temporary data tempData, err := common.GetTemporaryVoucherData(ctx, h.userdataStore, sessionId) if err != nil { diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 2f2e94b..f4c9f7c 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -12,10 +12,10 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/internal/storage" "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" + "git.grassecon.net/urdt/ussd/models" "git.grassecon.net/urdt/ussd/common" "github.com/alecthomas/assert/v2" @@ -122,7 +122,7 @@ func TestCreateAccount(t *testing.T) { name: "Test account creation success", serverResponse: &models.AccountResult{ TrackingId: "1234567890", - PublicKey: "0xD3adB33f", + PublicKey: "0xD3adB33f", }, expectedResult: resource.Result{ FlagSet: []uint32{flag_account_created}, @@ -176,7 +176,7 @@ func TestSaveFirstname(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -215,7 +215,7 @@ func TestSaveFamilyname(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -254,7 +254,7 @@ func TestSaveYoB(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -265,7 +265,7 @@ func TestSaveYoB(t *testing.T) { // Define test data yob := "1980" - + if err := store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(yob)); err != nil { t.Fatal(err) } @@ -293,7 +293,7 @@ func TestSaveLocation(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -304,7 +304,7 @@ func TestSaveLocation(t *testing.T) { // Define test data location := "Kilifi" - + if err := store.WriteEntry(ctx, sessionId, common.DATA_TEMPORARY_VALUE, []byte(location)); err != nil { t.Fatal(err) } @@ -332,7 +332,7 @@ func TestSaveOfferings(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -371,7 +371,7 @@ func TestSaveGender(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) - + fm, _ := NewFlagManager(flagsPath) flag_allow_update, _ := fm.GetFlag("flag_allow_update") @@ -1746,9 +1746,9 @@ func TestFetchCustodialBalances(t *testing.T) { } tests := []struct { - name string + name string balanceResponse *models.BalanceResult - expectedResult resource.Result + expectedResult resource.Result }{ { name: "Test when fetch custodial balances is not a success", @@ -1807,16 +1807,15 @@ func TestSetDefaultVoucher(t *testing.T) { expectedResult resource.Result }{ { - name: "Test no vouchers available", - vouchersResp: []dataserviceapi.TokenHoldings { - }, + name: "Test no vouchers available", + vouchersResp: []dataserviceapi.TokenHoldings{}, expectedResult: resource.Result{ FlagSet: []uint32{flag_no_active_voucher}, }, }, { name: "Test set default voucher when no active voucher is set", - vouchersResp: []dataserviceapi.TokenHoldings { + vouchersResp: []dataserviceapi.TokenHoldings{ dataserviceapi.TokenHoldings{ ContractAddress: "0x123", TokenSymbol: "TOKEN1",