diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index dd3efdb..7f3068f 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -19,9 +19,9 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" + "git.grassecon.net/urdt/ussd/common" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/utils" - "git.grassecon.net/urdt/ussd/common" "gopkg.in/leonelquinteros/gotext.v1" "git.grassecon.net/urdt/ussd/internal/storage" @@ -33,7 +33,6 @@ var ( translationDir = path.Join(scriptDir, "locale") okResponse *api.OKResponse errResponse *api.ErrResponse - backOption = []byte("0") ) // FlagManager handles centralized flag management @@ -334,13 +333,18 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil + firstName := string(input) + store := h.userdataStore + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + if allowUpdate { + temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME) + err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName)) + if err != nil { + return res, err } - firstName := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)) if err != nil { return res, err } @@ -357,20 +361,24 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil - } - familyName := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) + store := h.userdataStore + familyName := string(input) + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME) + err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) if err != nil { return res, err } } else { - return res, fmt.Errorf("a family name cannot be less than one character") + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)) + if err != nil { + return res, err + } } - return res, nil } @@ -382,10 +390,19 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou if !ok { return res, fmt.Errorf("missing session") } - if len(input) == 4 { - yob := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(yob)) + yob := string(input) + store := h.userdataStore + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB) + err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob)) + if err != nil { + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)) if err != nil { return res, err } @@ -402,13 +419,20 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - if bytes.Equal(input, backOption) { - return res, nil + location := string(input) + store := h.userdataStore + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION) + err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation)) + if err != nil { + return res, err } - location := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(location)) if err != nil { return res, err } @@ -426,14 +450,22 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re if !ok { return res, fmt.Errorf("missing session") } - if bytes.Equal(input, backOption) { - return res, nil - } gender := strings.Split(symbol, "_")[1] store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) - if err != nil { - return res, nil + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER) + err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender)) + if err != nil { + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(gender)) + if err != nil { + return res, err + } } return res, nil @@ -447,12 +479,22 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { - offerings := string(input) - store := h.userdataStore - err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)) + offerings := string(input) + store := h.userdataStore + + flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") + allowUpdate := h.st.MatchFlag(flag_allow_update, true) + + if allowUpdate { + temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS) + err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings)) if err != nil { - return res, nil + return res, err + } + } else { + err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)) + if err != nil { + return res, err } } diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index a960cfc..7c0689f 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -19,8 +19,8 @@ import ( "git.grassecon.net/urdt/ussd/internal/testutil/mocks" "git.grassecon.net/urdt/ussd/internal/testutil/testservice" - "git.grassecon.net/urdt/ussd/internal/utils" "git.grassecon.net/urdt/ussd/common" + "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" testdataloader "github.com/peteole/testdata-loader" @@ -174,8 +174,11 @@ func TestWithPersister_PanicWhenAlreadySet(t *testing.T) { } func TestSaveFirstname(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create new mocks mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -183,11 +186,13 @@ func TestSaveFirstname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + flagManager: fm.parser, + st: mockState, } // Call the method @@ -204,6 +209,9 @@ func TestSaveFirstname(t *testing.T) { func TestSaveFamilyname(t *testing.T) { // Create a new instance of UserDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -211,11 +219,13 @@ func TestSaveFamilyname(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -288,8 +298,11 @@ func TestSaveTemporaryPin(t *testing.T) { } func TestSaveYoB(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create new instances mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -297,11 +310,13 @@ func TestSaveYoB(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_YOB, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -318,6 +333,9 @@ func TestSaveYoB(t *testing.T) { func TestSaveLocation(t *testing.T) { // Create a new instance of MockMyDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -325,11 +343,13 @@ func TestSaveLocation(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_LOCATION, []byte(yob)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(yob)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -346,6 +366,9 @@ func TestSaveLocation(t *testing.T) { func TestSaveOfferings(t *testing.T) { // Create a new instance of MockUserDataStore mockStore := new(mocks.MockUserDataStore) + mockState := state.NewState(16) + + fm, err := NewFlagManager(flagsPath) // Define test data sessionId := "session123" @@ -353,11 +376,13 @@ func TestSaveOfferings(t *testing.T) { ctx := context.WithValue(context.Background(), "SessionId", sessionId) // Set up the expected behavior of the mock - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)).Return(nil) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, + st: mockState, + flagManager: fm.parser, } // Call the method @@ -372,10 +397,12 @@ func TestSaveOfferings(t *testing.T) { } func TestSaveGender(t *testing.T) { - // Create a new instance of MockMyDataStore + // Create a new mock instances mockStore := new(mocks.MockUserDataStore) mockState := state.NewState(16) + fm, _ := NewFlagManager(flagsPath) + // Define the session ID and context sessionId := "session123" ctx := context.WithValue(context.Background(), "SessionId", sessionId) @@ -415,16 +442,17 @@ func TestSaveGender(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Set up expectations for the mock database if tt.expectCall { - expectedKey := utils.DATA_GENDER + expectedKey := utils.DATA_TEMPORARY_GENDER mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil) } else { - mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil) + mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)).Return(nil) } mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol) // Create the Handlers instance with the mock store h := &Handlers{ userdataStore: mockStore, st: mockState, + flagManager: fm.parser, } // Call the method @@ -435,9 +463,9 @@ func TestSaveGender(t *testing.T) { // Verify expectations if tt.expectCall { - mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) } else { - mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)) + mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)) } }) } diff --git a/internal/utils/db.go b/internal/utils/db.go index 802e092..61970ae 100644 --- a/internal/utils/db.go +++ b/internal/utils/db.go @@ -14,11 +14,17 @@ const ( DATA_CUSTODIAL_ID DATA_ACCOUNT_PIN DATA_ACCOUNT_STATUS + DATA_TEMPORARY_FIRST_NAME DATA_FIRST_NAME + DATA_TEMPORARY_FAMILY_NAME DATA_FAMILY_NAME + DATA_TEMPORARY_YOB DATA_YOB + DATA_TEMPORARY_LOCATION DATA_LOCATION + DATA_TEMPORARY_GENDER DATA_GENDER + DATA_TEMPORARY_OFFERINGS DATA_OFFERINGS DATA_RECIPIENT DATA_AMOUNT @@ -33,6 +39,7 @@ const ( DATA_ACTIVE_DECIMAL DATA_TEMPORARY_ADDRESS DATA_ACTIVE_ADDRESS + ) func typToBytes(typ DataTyp) []byte { diff --git a/services/registration/enter_familyname.vis b/services/registration/enter_familyname.vis index 5a684ed..5db4c17 100644 --- a/services/registration/enter_familyname.vis +++ b/services/registration/enter_familyname.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_familyname flag_allow_update 1 MOUT back 0 HALT LOAD save_familyname 0 diff --git a/services/registration/enter_location.vis b/services/registration/enter_location.vis index c8da2dd..8966872 100644 --- a/services/registration/enter_location.vis +++ b/services/registration/enter_location.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_location flag_allow_update 1 MOUT back 0 HALT LOAD save_location 0 diff --git a/services/registration/enter_name.vis b/services/registration/enter_name.vis index 799b2a1..f853d0a 100644 --- a/services/registration/enter_name.vis +++ b/services/registration/enter_name.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_firstname flag_allow_update 1 MOUT back 0 HALT LOAD save_firstname 0 diff --git a/services/registration/enter_offerings.vis b/services/registration/enter_offerings.vis index 26e4b61..5cc7977 100644 --- a/services/registration/enter_offerings.vis +++ b/services/registration/enter_offerings.vis @@ -1,5 +1,5 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_offerings flag_allow_update 1 LOAD save_offerings 0 MOUT back 0 HALT diff --git a/services/registration/enter_yob.vis b/services/registration/enter_yob.vis index 40bf3f4..c74aeed 100644 --- a/services/registration/enter_yob.vis +++ b/services/registration/enter_yob.vis @@ -1,10 +1,10 @@ CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 -LOAD save_yob 0 +CATCH update_yob flag_allow_update 1 MOUT back 0 HALT LOAD verify_yob 0 CATCH incorrect_date_format flag_incorrect_date_format 1 +LOAD save_yob 0 RELOAD save_yob INCMP _ 0 INCMP pin_entry * diff --git a/services/registration/set_female.vis b/services/registration/set_female.vis index 723b080..e211ada 100644 --- a/services/registration/set_female.vis +++ b/services/registration/set_female.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/set_male.vis b/services/registration/set_male.vis index 723b080..e211ada 100644 --- a/services/registration/set_male.vis +++ b/services/registration/set_male.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/set_unspecified.vis b/services/registration/set_unspecified.vis index 723b080..e211ada 100644 --- a/services/registration/set_unspecified.vis +++ b/services/registration/set_unspecified.vis @@ -1,4 +1,4 @@ LOAD save_gender 0 CATCH incorrect_pin flag_incorrect_pin 1 -CATCH profile_update_success flag_allow_update 1 +CATCH update_gender flag_allow_update 1 MOVE pin_entry diff --git a/services/registration/update_age b/services/registration/update_age new file mode 100644 index 0000000..76ca306 --- /dev/null +++ b/services/registration/update_age @@ -0,0 +1,2 @@ +RELOAD save_yob +CATCH profile_update_success flag_allow_update 1 \ No newline at end of file diff --git a/services/registration/update_familyname.vis b/services/registration/update_familyname.vis new file mode 100644 index 0000000..7cd4d9f --- /dev/null +++ b/services/registration/update_familyname.vis @@ -0,0 +1,2 @@ +RELOAD save_familyname +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_firstname.vis b/services/registration/update_firstname.vis new file mode 100644 index 0000000..dca7036 --- /dev/null +++ b/services/registration/update_firstname.vis @@ -0,0 +1,2 @@ +RELOAD save_firstname +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_gender.vis b/services/registration/update_gender.vis new file mode 100644 index 0000000..506a56a --- /dev/null +++ b/services/registration/update_gender.vis @@ -0,0 +1,2 @@ +RELOAD save_gender +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_location.vis b/services/registration/update_location.vis new file mode 100644 index 0000000..16c4ea2 --- /dev/null +++ b/services/registration/update_location.vis @@ -0,0 +1,2 @@ +RELOAD save_location +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_offerings.vis b/services/registration/update_offerings.vis new file mode 100644 index 0000000..4aeed74 --- /dev/null +++ b/services/registration/update_offerings.vis @@ -0,0 +1,2 @@ +RELOAD save_offerings +CATCH profile_update_success flag_allow_update 1 diff --git a/services/registration/update_yob.vis b/services/registration/update_yob.vis new file mode 100644 index 0000000..a9388ae --- /dev/null +++ b/services/registration/update_yob.vis @@ -0,0 +1,2 @@ +RELOAD save_yob +CATCH profile_update_success flag_allow_update 1