From 72d5c186dd7a04b738262263ed5c785103f5e88f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 28 Oct 2024 15:18:40 +0300 Subject: [PATCH 01/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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/56] 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 b404ae95fbfa4fdec0b7c84e7c7486618a754eca Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 14:30:38 +0300 Subject: [PATCH 26/56] 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 27/56] 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 28/56] 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 29/56] 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 30/56] 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 31/56] 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 32/56] 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 d93a26f9b0d2ae02c9798825efac879d09630cf0 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 30 Oct 2024 17:58:52 +0300 Subject: [PATCH 33/56] 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 34/56] 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 35/56] 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 36/56] 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 37/56] 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 38/56] 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 39/56] 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 40/56] 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 c4078c528005012a6f3053ff55a6e7cbbc108c0b Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 09:21:46 +0300 Subject: [PATCH 41/56] 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 42/56] 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 ac0b4b2ed1de7ab609441b67feaba1c5a58fcafe Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Thu, 31 Oct 2024 20:08:30 +0300 Subject: [PATCH 43/56] 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 44/56] 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 45/56] 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 46/56] 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 47/56] 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 48/56] 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 49/56] 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 50/56] 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 51/56] 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 0014693ba8b3b8f1545e59e3cf66bf6bf71caebb Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 06:39:37 +0300 Subject: [PATCH 52/56] 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 53/56] 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 54/56] 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 332074375aee0010d9cbf37f8738bf12e432810d Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Fri, 1 Nov 2024 16:44:54 +0300 Subject: [PATCH 55/56] 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 56/56] 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 }