From 68e4c9af036e2c38499f9e7b2c7ec1a77dec1e24 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 6 Jan 2025 21:00:34 +0300 Subject: [PATCH 01/21] add key for incorrect pin attempts --- common/db.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/db.go b/common/db.go index a5cf1c1..5e2fc4c 100644 --- a/common/db.go +++ b/common/db.go @@ -7,7 +7,7 @@ import ( "git.defalsify.org/vise.git/logging" ) -// DataType is a subprefix value used in association with vise/db.DATATYPE_USERDATA. +// DataType is a subprefix value used in association with vise/db.DATATYPE_USERDATA. // // All keys are used only within the context of a single account. Unless otherwise specified, the user context is the session id. // @@ -55,6 +55,8 @@ const ( DATA_ACTIVE_DECIMAL // EVM address of the currently active voucher DATA_ACTIVE_ADDRESS + //Holds count of the number of incorrect PIN attempts + DATA_INCORRECT_PIN_ATTEMPTS ) const ( From b37f2a0a110cc5e2c50f76eeac854144d61363c3 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 6 Jan 2025 21:06:54 +0300 Subject: [PATCH 02/21] add flag for when an account has been blocked --- services/registration/pp.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/registration/pp.csv b/services/registration/pp.csv index 26a8833..aa1eb05 100644 --- a/services/registration/pp.csv +++ b/services/registration/pp.csv @@ -28,3 +28,5 @@ flag,flag_gender_set,34,this is set when the gender of the profile is set flag,flag_location_set,35,this is set when the location of the profile is set flag,flag_offerings_set,36,this is set when the offerings of the profile is set flag,flag_back_set,37,this is set when it is a back navigation +flag,flag_account_blocked,38,this is set when an account has been blocked after the allowed incorrect PIN attempts have been exceeded + From 90df0eefc39dc62ee6c32b96e1de16705a4a2442 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 6 Jan 2025 22:53:59 +0300 Subject: [PATCH 03/21] add value for allowed number of PIN attempts --- common/pin.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/pin.go b/common/pin.go index 6db9d15..d42fb58 100644 --- a/common/pin.go +++ b/common/pin.go @@ -8,7 +8,8 @@ import ( // Define the regex pattern as a constant const ( - pinPattern = `^\d{4}$` + pinPattern = `^\d{4}$` + AllowedPINAttempts = uint8(3) ) // checks whether the given input is a 4 digit number From 562bd4fa241b9759cf344a5a2cad85e65bf1935e Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Mon, 6 Jan 2025 22:54:31 +0300 Subject: [PATCH 04/21] check for incorrect pin --- internal/handlers/ussd/menuhandler.go | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dfdbd02..70fd305 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -739,6 +739,7 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res res.FlagReset = append(res.FlagReset, flag_account_authorized) } } else { + h.countIncorrectPINAttempts(ctx, sessionId) res.FlagSet = append(res.FlagSet, flag_incorrect_pin) res.FlagReset = append(res.FlagReset, flag_account_authorized) return res, nil @@ -752,6 +753,24 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res // ResetIncorrectPin resets the incorrect pin flag after a new PIN attempt. func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result + store := h.userdataStore + + sessionId, ok := ctx.Value("SessionId").(string) + if !ok { + return res, fmt.Errorf("missing session") + } + currentWrongPinAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) + if err != nil { + if !db.IsNotFound(err) { + return res, err + } + } + pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) + remainingPINAttempts := common.AllowedPINAttempts - uint8(pinAttemptsValue) + if remainingPINAttempts < common.AllowedPINAttempts { + res.Content = string(remainingPINAttempts) + } + flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") res.FlagReset = append(res.FlagReset, flag_incorrect_pin) return res, nil @@ -2075,3 +2094,28 @@ func (h *Handlers) UpdateAllProfileItems(ctx context.Context, sym string, input } return res, nil } + +func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId string) { + var pinAttemptsCount uint8 + store := h.userdataStore + + currentWrongPinAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) + if err != nil { + if db.IsNotFound(err) { + //First time Wrong PIN attempt: initialize with a count of 1 + pinAttemptsCount = 1 + err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(pinAttemptsCount)))) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", currentWrongPinAttempts, "error", err) + } + return + } + } + pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) + pinAttemptsCount = uint8(pinAttemptsValue) + 1 + + err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(pinAttemptsCount)))) + if err != nil { + logg.ErrorCtxf(ctx, "failed to write incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", pinAttemptsCount, "error", err) + } +} From f83f53904668883a4f71b2dc78b282c7a287e861 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 7 Jan 2025 10:48:59 +0300 Subject: [PATCH 05/21] add node to show remaining pin attempts --- services/registration/incorrect_pin | 2 +- services/registration/incorrect_pin_swa | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/registration/incorrect_pin b/services/registration/incorrect_pin index 7fcf610..0e34cd1 100644 --- a/services/registration/incorrect_pin +++ b/services/registration/incorrect_pin @@ -1 +1 @@ -Incorrect PIN \ No newline at end of file +Incorrect PIN.You have: {{.reset_incorrect}} remaining attempt(s). \ No newline at end of file diff --git a/services/registration/incorrect_pin_swa b/services/registration/incorrect_pin_swa index 34a0b28..8a8b913 100644 --- a/services/registration/incorrect_pin_swa +++ b/services/registration/incorrect_pin_swa @@ -1 +1 @@ -PIN ulioeka sio sahihi \ No newline at end of file +PIN ulioeka sio sahihi,una majaribio: {{.reset_incorrect}} yaliyobaki \ No newline at end of file From 11d30583a432088503388ba35cc479fc719fe2c9 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 7 Jan 2025 10:50:30 +0300 Subject: [PATCH 06/21] map content of reset_incorrect and catch blocked account --- services/registration/incorrect_pin.vis | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/registration/incorrect_pin.vis b/services/registration/incorrect_pin.vis index 844f3d6..167364a 100644 --- a/services/registration/incorrect_pin.vis +++ b/services/registration/incorrect_pin.vis @@ -1,5 +1,7 @@ LOAD reset_incorrect 0 RELOAD reset_incorrect +MAP reset_incorrect +CATCH blocked_account flag_account_blocked 1 MOUT retry 1 MOUT quit 9 HALT From ee442daefa0c04db6b91183d37589cdf74b76795 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 7 Jan 2025 14:03:53 +0300 Subject: [PATCH 07/21] add blocked account node --- services/registration/blocked_account | 1 + services/registration/blocked_account.vis | 3 +++ services/registration/blocked_account_swa | 1 + 3 files changed, 5 insertions(+) create mode 100644 services/registration/blocked_account create mode 100644 services/registration/blocked_account.vis create mode 100644 services/registration/blocked_account_swa diff --git a/services/registration/blocked_account b/services/registration/blocked_account new file mode 100644 index 0000000..9a34267 --- /dev/null +++ b/services/registration/blocked_account @@ -0,0 +1 @@ +Your account has been locked.For help on how to unblock your account,contact support at: 0757628885 diff --git a/services/registration/blocked_account.vis b/services/registration/blocked_account.vis new file mode 100644 index 0000000..d5e6b2d --- /dev/null +++ b/services/registration/blocked_account.vis @@ -0,0 +1,3 @@ +MOUT quit 9 +HALT +INCMP quit 9 diff --git a/services/registration/blocked_account_swa b/services/registration/blocked_account_swa new file mode 100644 index 0000000..c00243b --- /dev/null +++ b/services/registration/blocked_account_swa @@ -0,0 +1 @@ +Akaunti yako imefungwa.Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885 \ No newline at end of file From c15958a1ad8d98cc684363bc181bd4627b5684a4 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 7 Jan 2025 14:32:44 +0300 Subject: [PATCH 08/21] reset incorrect pin attempts on correct entry --- internal/handlers/ussd/menuhandler.go | 54 ++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 70fd305..5582265 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -734,12 +734,23 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res if h.st.MatchFlag(flag_account_authorized, false) { res.FlagReset = append(res.FlagReset, flag_incorrect_pin) res.FlagSet = append(res.FlagSet, flag_allow_update, flag_account_authorized) + err := h.resetIncorrectPINAttempts(ctx, sessionId) + if err != nil { + return res, err + } } else { res.FlagSet = append(res.FlagSet, flag_allow_update) res.FlagReset = append(res.FlagReset, flag_account_authorized) + err := h.resetIncorrectPINAttempts(ctx, sessionId) + if err != nil { + return res, err + } } } else { - h.countIncorrectPINAttempts(ctx, sessionId) + err := h.countIncorrectPINAttempts(ctx, sessionId) + if err != nil { + return res, err + } res.FlagSet = append(res.FlagSet, flag_incorrect_pin) res.FlagReset = append(res.FlagReset, flag_account_authorized) return res, nil @@ -755,10 +766,16 @@ func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []by var res resource.Result store := h.userdataStore + flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") + flag_account_blocked, _ := h.flagManager.GetFlag("flag_account_blocked") + sessionId, ok := ctx.Value("SessionId").(string) if !ok { return res, fmt.Errorf("missing session") } + + res.FlagReset = append(res.FlagReset, flag_incorrect_pin) + currentWrongPinAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) if err != nil { if !db.IsNotFound(err) { @@ -767,12 +784,14 @@ func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []by } pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) remainingPINAttempts := common.AllowedPINAttempts - uint8(pinAttemptsValue) + if remainingPINAttempts == 0 { + res.FlagSet = append(res.FlagSet, flag_account_blocked) + return res, nil + } if remainingPINAttempts < common.AllowedPINAttempts { - res.Content = string(remainingPINAttempts) + res.Content = strconv.Itoa(int(remainingPINAttempts)) } - flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") - res.FlagReset = append(res.FlagReset, flag_incorrect_pin) return res, nil } @@ -2095,7 +2114,7 @@ func (h *Handlers) UpdateAllProfileItems(ctx context.Context, sym string, input return res, nil } -func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId string) { +func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId string) error { var pinAttemptsCount uint8 store := h.userdataStore @@ -2107,8 +2126,9 @@ func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId stri err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(pinAttemptsCount)))) if err != nil { logg.ErrorCtxf(ctx, "failed to write incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", currentWrongPinAttempts, "error", err) + return err } - return + return nil } } pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) @@ -2117,5 +2137,27 @@ func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId stri err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(pinAttemptsCount)))) if err != nil { logg.ErrorCtxf(ctx, "failed to write incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", pinAttemptsCount, "error", err) + return err } + return nil +} + +func (h *Handlers) resetIncorrectPINAttempts(ctx context.Context, sessionId string) error { + store := h.userdataStore + currentWrongPinAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) + if err != nil { + if db.IsNotFound(err) { + return nil + } + return err + } + remainingPINAttempts, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) + if remainingPINAttempts <= uint64(common.AllowedPINAttempts) { + err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(string("0"))) + if err != nil { + logg.ErrorCtxf(ctx, "failed to reset incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", common.AllowedPINAttempts, "error", err) + return err + } + } + return nil } From 64fba916700508d8f3ab6c1ba29ca4b8d1c5c618 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Tue, 7 Jan 2025 14:38:44 +0300 Subject: [PATCH 09/21] catch blocked account --- services/registration/root.vis | 1 + 1 file changed, 1 insertion(+) diff --git a/services/registration/root.vis b/services/registration/root.vis index 02ef9e9..102e6e5 100644 --- a/services/registration/root.vis +++ b/services/registration/root.vis @@ -1,3 +1,4 @@ +CATCH blocked_account flag_account_blocked 1 CATCH select_language flag_language_set 0 CATCH terms flag_account_created 0 LOAD check_account_status 0 From 07b061a68b4d034a607cc38ab9c217f0c3c2eee5 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 09:26:53 +0300 Subject: [PATCH 10/21] remove blocked account templates --- services/registration/blocked_account | 1 - services/registration/blocked_account_swa | 1 - 2 files changed, 2 deletions(-) delete mode 100644 services/registration/blocked_account delete mode 100644 services/registration/blocked_account_swa diff --git a/services/registration/blocked_account b/services/registration/blocked_account deleted file mode 100644 index 9a34267..0000000 --- a/services/registration/blocked_account +++ /dev/null @@ -1 +0,0 @@ -Your account has been locked.For help on how to unblock your account,contact support at: 0757628885 diff --git a/services/registration/blocked_account_swa b/services/registration/blocked_account_swa deleted file mode 100644 index c00243b..0000000 --- a/services/registration/blocked_account_swa +++ /dev/null @@ -1 +0,0 @@ -Akaunti yako imefungwa.Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885 \ No newline at end of file From 50c7ff104616994ce532078483f2b66433a27dfe Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 09:27:45 +0300 Subject: [PATCH 11/21] register handler to show blocked account message --- internal/handlers/handlerservice.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 1da28c3..0d49b0c 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -128,6 +128,7 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountServiceIn ls.DbRs.AddLocalFunc("view_statement", ussdHandlers.ViewTransactionStatement) ls.DbRs.AddLocalFunc("update_all_profile_items", ussdHandlers.UpdateAllProfileItems) ls.DbRs.AddLocalFunc("set_back", ussdHandlers.SetBack) + ls.DbRs.AddLocalFunc("show_blocked_account", ussdHandlers.ShowBlockedAccount) return ussdHandlers, nil } From 3004698d5bdeab0cc0def616a97de4f93e407e25 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 09:28:31 +0300 Subject: [PATCH 12/21] add a message for a blocked account --- services/registration/locale/swa/default.po | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/registration/locale/swa/default.po b/services/registration/locale/swa/default.po index 4bf876b..ab238e7 100644 --- a/services/registration/locale/swa/default.po +++ b/services/registration/locale/swa/default.po @@ -10,6 +10,9 @@ msgstr "Asante kwa kutumia huduma ya Sarafu. Kwaheri!" msgid "For more help,please call: 0757628885" msgstr "Kwa usaidizi zaidi,piga: 0757628885" +msgid "Your account has been locked.For help on how to unblock your account,contact support at: 0757628885" +msgstr "Akaunti yako imefungwa.Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885" + msgid "Balance: %s\n" msgstr "Salio: %s\n" From 4fe64a774748f2936ea55bc4bf69f6cfb1736a80 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 09:29:00 +0300 Subject: [PATCH 13/21] show message for a blocked account --- services/registration/blocked_account.vis | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/registration/blocked_account.vis b/services/registration/blocked_account.vis index d5e6b2d..d8adab2 100644 --- a/services/registration/blocked_account.vis +++ b/services/registration/blocked_account.vis @@ -1,3 +1,2 @@ -MOUT quit 9 +LOAD show_blocked_account 0 HALT -INCMP quit 9 From 4d72ae0313ad78052979c0ddcfbe25de94185fd3 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 09:30:51 +0300 Subject: [PATCH 14/21] add handler showing a message for a blocked account --- internal/handlers/ussd/menuhandler.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index 5582265..2fcf92e 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -878,6 +878,16 @@ func (h *Handlers) QuitWithHelp(ctx context.Context, sym string, input []byte) ( return res, nil } +// ShowBlockedAccount displays a message after an account has been blocked and how to reach support. +func (h *Handlers) ShowBlockedAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) { + var res resource.Result + code := codeFromCtx(ctx) + l := gotext.NewLocale(translationDir, code) + l.AddDomain("default") + res.Content = l.Get("Your account has been locked.For help on how to unblock your account,contact support at: 0757628885") + return res, nil +} + // VerifyYob verifies the length of the given input. func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { var res resource.Result @@ -2114,6 +2124,7 @@ func (h *Handlers) UpdateAllProfileItems(ctx context.Context, sym string, input return res, nil } +// countIncorrectPINAttempts keeps track of the number of incorrect PIN attempts func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId string) error { var pinAttemptsCount uint8 store := h.userdataStore @@ -2142,6 +2153,7 @@ func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId stri return nil } +// resetIncorrectPINAttempts resets the number of incorrect PIN attempts after a correct PIN entry func (h *Handlers) resetIncorrectPINAttempts(ctx context.Context, sessionId string) error { store := h.userdataStore currentWrongPinAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) From 7f3294a8a2e4ad188801d867eb793b11b1ea2c4f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 11:47:41 +0300 Subject: [PATCH 15/21] update tests --- internal/handlers/ussd/menuhandler_test.go | 101 ++++++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 914dffc..5914821 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "path" + "strconv" "strings" "testing" @@ -907,37 +908,79 @@ func TestResetAccountAuthorized(t *testing.T) { } func TestIncorrectPinReset(t *testing.T) { + sessionId := "session123" + ctx, store := InitializeTestStore(t) fm, err := NewFlagManager(flagsPath) + if err != nil { log.Fatal(err) } flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") + flag_account_blocked, _ := fm.parser.GetFlag("flag_account_blocked") + + ctx = context.WithValue(ctx, "SessionId", sessionId) // Define test cases tests := []struct { name string input []byte + attempts uint8 expectedResult resource.Result }{ { - name: "Test incorrect pin reset", + name: "Test when incorrect PIN attempts is 2", input: []byte(""), expectedResult: resource.Result{ FlagReset: []uint32{flag_incorrect_pin}, + Content: "1", //Expected remaining PIN attempts }, + attempts: 2, + }, + { + name: "Test incorrect pin reset when incorrect PIN attempts is 1", + input: []byte(""), + expectedResult: resource.Result{ + FlagReset: []uint32{flag_incorrect_pin}, + Content: "2", //Expected remaining PIN attempts + }, + attempts: 1, + }, + { + name: "Test incorrect pin reset when incorrect PIN attempts is 1", + input: []byte(""), + expectedResult: resource.Result{ + FlagReset: []uint32{flag_incorrect_pin}, + Content: "2", //Expected remaining PIN attempts + }, + attempts: 1, + }, + { + name: "Test incorrect pin reset when incorrect PIN attempts is 3(account expected to be blocked)", + input: []byte(""), + expectedResult: resource.Result{ + FlagReset: []uint32{flag_incorrect_pin}, + FlagSet: []uint32{flag_account_blocked}, + }, + attempts: 3, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + + if err := store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(tt.attempts)))); err != nil { + t.Fatal(err) + } + // Create the Handlers instance with the mock flag manager h := &Handlers{ - flagManager: fm.parser, + flagManager: fm.parser, + userdataStore: store, } // Call the method - res, err := h.ResetIncorrectPin(context.Background(), "reset_incorrect_pin", tt.input) + res, err := h.ResetIncorrectPin(ctx, "reset_incorrect_pin", tt.input) if err != nil { t.Error(err) } @@ -2190,3 +2233,55 @@ func TestGetVoucherDetails(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedResult, res) } + +func TestCountIncorrectPINAttempts(t *testing.T) { + ctx, store := InitializeTestStore(t) + sessionId := "session123" + ctx = context.WithValue(ctx, "SessionId", sessionId) + attempts := uint8(2) + + h := &Handlers{ + userdataStore: store, + } + err := store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(attempts)))) + if err != nil { + t.Logf(err.Error()) + } + err = h.countIncorrectPINAttempts(ctx, sessionId) + if err != nil { + t.Logf(err.Error()) + } + + attemptsAfterCount, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) + if err != nil { + t.Logf(err.Error()) + } + pinAttemptsValue, _ := strconv.ParseUint(string(attemptsAfterCount), 0, 64) + pinAttemptsCount := uint8(pinAttemptsValue) + expectedAttempts := attempts + 1 + assert.Equal(t, pinAttemptsCount, expectedAttempts) + +} + +func TestResetIncorrectPINAttempts(t *testing.T) { + ctx, store := InitializeTestStore(t) + sessionId := "session123" + ctx = context.WithValue(ctx, "SessionId", sessionId) + + err := store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(string("2"))) + if err != nil { + t.Logf(err.Error()) + } + + h := &Handlers{ + userdataStore: store, + } + h.resetIncorrectPINAttempts(ctx, sessionId) + incorrectAttempts, err := store.ReadEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS) + + if err != nil { + t.Logf(err.Error()) + } + assert.Equal(t, "0", string(incorrectAttempts)) + +} From 8d477356f38e26112d89e0e70e3e48caa50a991f Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 11:47:55 +0300 Subject: [PATCH 16/21] update tests --- menutraversal_test/group_test.json | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/menutraversal_test/group_test.json b/menutraversal_test/group_test.json index f35beb9..0998c11 100644 --- a/menutraversal_test/group_test.json +++ b/menutraversal_test/group_test.json @@ -54,7 +54,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", @@ -95,7 +95,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", @@ -107,8 +107,7 @@ }, { "input": "0", - "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" - + "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" }, { "input": "0", @@ -141,7 +140,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", @@ -153,8 +152,7 @@ }, { "input": "0", - "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" - + "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" }, { "input": "0", @@ -195,7 +193,7 @@ }, { "input": "1", - "expectedContent": "Enter your year of birth\n0:Back" + "expectedContent": "Enter your year of birth\n0:Back" }, { "input": "1940", @@ -258,7 +256,6 @@ "input": "0", "expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" } - ] }, { @@ -443,10 +440,4 @@ ] } ] -} - - - - - - +} \ No newline at end of file From ed6651697aff2b56d012704fb3e0883888283d65 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 14:13:14 +0300 Subject: [PATCH 17/21] chore : add variable description to AllowedPINAttempts --- common/pin.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/pin.go b/common/pin.go index d42fb58..13f21b3 100644 --- a/common/pin.go +++ b/common/pin.go @@ -6,10 +6,13 @@ import ( "golang.org/x/crypto/bcrypt" ) -// Define the regex pattern as a constant const ( - pinPattern = `^\d{4}$` + // Define the regex pattern as a constant + pinPattern = `^\d{4}$` + + //Allowed incorrect PIN attempts AllowedPINAttempts = uint8(3) + ) // checks whether the given input is a 4 digit number From 477b4cf8f6471e331d9e624bb90a53ef4ad2c9d8 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 14:15:45 +0300 Subject: [PATCH 18/21] chore : rename remainingPINAttempts to currentWrongPinAttemptsCount --- internal/handlers/ussd/menuhandler.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index a06c274..b76cc7f 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -2163,8 +2163,8 @@ func (h *Handlers) resetIncorrectPINAttempts(ctx context.Context, sessionId stri } return err } - remainingPINAttempts, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) - if remainingPINAttempts <= uint64(common.AllowedPINAttempts) { + currentWrongPinAttemptsCount, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) + if currentWrongPinAttemptsCount <= uint64(common.AllowedPINAttempts) { err = store.WriteEntry(ctx, sessionId, common.DATA_INCORRECT_PIN_ATTEMPTS, []byte(string("0"))) if err != nil { logg.ErrorCtxf(ctx, "failed to reset incorrect PIN attempts ", "key", common.DATA_INCORRECT_PIN_ATTEMPTS, "value", common.AllowedPINAttempts, "error", err) From 2ff9fed3c5686a70a0dccd9f1f885b47a01f908a Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 14:51:15 +0300 Subject: [PATCH 19/21] chore: rename countIncorrectPINAttempts to incrementIncorrectPINAttempts --- internal/handlers/ussd/menuhandler.go | 8 ++++---- internal/handlers/ussd/menuhandler_test.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index b76cc7f..f831696 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -747,7 +747,7 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res } } } else { - err := h.countIncorrectPINAttempts(ctx, sessionId) + err := h.incrementIncorrectPINAttempts(ctx, sessionId) if err != nil { return res, err } @@ -884,7 +884,7 @@ func (h *Handlers) ShowBlockedAccount(ctx context.Context, sym string, input []b code := codeFromCtx(ctx) l := gotext.NewLocale(translationDir, code) l.AddDomain("default") - res.Content = l.Get("Your account has been locked.For help on how to unblock your account,contact support at: 0757628885") + res.Content = l.Get("Your account has been locked.For help on how to unblock your account, contact support at: 0757628885") return res, nil } @@ -2124,8 +2124,8 @@ func (h *Handlers) UpdateAllProfileItems(ctx context.Context, sym string, input return res, nil } -// countIncorrectPINAttempts keeps track of the number of incorrect PIN attempts -func (h *Handlers) countIncorrectPINAttempts(ctx context.Context, sessionId string) error { +// incrementIncorrectPINAttempts keeps track of the number of incorrect PIN attempts +func (h *Handlers) incrementIncorrectPINAttempts(ctx context.Context, sessionId string) error { var pinAttemptsCount uint8 store := h.userdataStore diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 5914821..af1380d 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -2247,7 +2247,7 @@ func TestCountIncorrectPINAttempts(t *testing.T) { if err != nil { t.Logf(err.Error()) } - err = h.countIncorrectPINAttempts(ctx, sessionId) + err = h.incrementIncorrectPINAttempts(ctx, sessionId) if err != nil { t.Logf(err.Error()) } From efdb52bccde15e6639fdf1b7175da3b64863de37 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 14:52:40 +0300 Subject: [PATCH 20/21] chore: add space after punctuation --- menutraversal_test/group_test.json | 6 +++--- services/registration/incorrect_pin | 2 +- services/registration/incorrect_pin_swa | 2 +- services/registration/locale/swa/default.po | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/menutraversal_test/group_test.json b/menutraversal_test/group_test.json index 0998c11..0ffb49f 100644 --- a/menutraversal_test/group_test.json +++ b/menutraversal_test/group_test.json @@ -54,7 +54,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", @@ -95,7 +95,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", @@ -140,7 +140,7 @@ }, { "input": "1235", - "expectedContent": "Incorrect PIN.You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" + "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit" }, { "input": "1", diff --git a/services/registration/incorrect_pin b/services/registration/incorrect_pin index 0e34cd1..13a9562 100644 --- a/services/registration/incorrect_pin +++ b/services/registration/incorrect_pin @@ -1 +1 @@ -Incorrect PIN.You have: {{.reset_incorrect}} remaining attempt(s). \ No newline at end of file +Incorrect PIN. You have: {{.reset_incorrect}} remaining attempt(s). \ No newline at end of file diff --git a/services/registration/incorrect_pin_swa b/services/registration/incorrect_pin_swa index 8a8b913..ed22beb 100644 --- a/services/registration/incorrect_pin_swa +++ b/services/registration/incorrect_pin_swa @@ -1 +1 @@ -PIN ulioeka sio sahihi,una majaribio: {{.reset_incorrect}} yaliyobaki \ No newline at end of file +PIN ulioeka sio sahihi, una majaribio: {{.reset_incorrect}} yaliyobaki \ No newline at end of file diff --git a/services/registration/locale/swa/default.po b/services/registration/locale/swa/default.po index 797c703..4effc1e 100644 --- a/services/registration/locale/swa/default.po +++ b/services/registration/locale/swa/default.po @@ -10,7 +10,7 @@ msgstr "Asante kwa kutumia huduma ya Sarafu. Kwaheri!" msgid "For more help, please call: 0757628885" msgstr "Kwa usaidizi zaidi, piga: 0757628885" -msgid "Your account has been locked.For help on how to unblock your account,contact support at: 0757628885" +msgid "Your account has been locked.For help on how to unblock your account, contact support at: 0757628885" msgstr "Akaunti yako imefungwa.Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885" msgid "Balance: %s\n" From b698f081363514907082d9df29520849a37cd8b7 Mon Sep 17 00:00:00 2001 From: Carlosokumu Date: Wed, 8 Jan 2025 15:27:10 +0300 Subject: [PATCH 21/21] chore: add space after punctuation --- internal/handlers/ussd/menuhandler.go | 2 +- services/registration/locale/swa/default.po | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index f831696..607b812 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -884,7 +884,7 @@ func (h *Handlers) ShowBlockedAccount(ctx context.Context, sym string, input []b code := codeFromCtx(ctx) l := gotext.NewLocale(translationDir, code) l.AddDomain("default") - res.Content = l.Get("Your account has been locked.For help on how to unblock your account, contact support at: 0757628885") + res.Content = l.Get("Your account has been locked. For help on how to unblock your account, contact support at: 0757628885") return res, nil } diff --git a/services/registration/locale/swa/default.po b/services/registration/locale/swa/default.po index 4effc1e..6155063 100644 --- a/services/registration/locale/swa/default.po +++ b/services/registration/locale/swa/default.po @@ -10,8 +10,8 @@ msgstr "Asante kwa kutumia huduma ya Sarafu. Kwaheri!" msgid "For more help, please call: 0757628885" msgstr "Kwa usaidizi zaidi, piga: 0757628885" -msgid "Your account has been locked.For help on how to unblock your account, contact support at: 0757628885" -msgstr "Akaunti yako imefungwa.Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885" +msgid "Your account has been locked. For help on how to unblock your account, contact support at: 0757628885" +msgstr "Akaunti yako imefungwa. Kwa usaidizi wa jinsi ya kufungua akaunti yako, wasiliana na usaidizi kwa: 0757628885" msgid "Balance: %s\n" msgstr "Salio: %s\n"