wip-flag-migration #28
@ -16,7 +16,6 @@ import (
|
|||||||
"git.defalsify.org/vise.git/resource"
|
"git.defalsify.org/vise.git/resource"
|
||||||
"git.defalsify.org/vise.git/state"
|
"git.defalsify.org/vise.git/state"
|
||||||
"git.grassecon.net/urdt/ussd/internal/handlers/server"
|
"git.grassecon.net/urdt/ussd/internal/handlers/server"
|
||||||
"git.grassecon.net/urdt/ussd/internal/models"
|
|
||||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||||
"github.com/graygnuorg/go-gdbm"
|
"github.com/graygnuorg/go-gdbm"
|
||||||
"gopkg.in/leonelquinteros/gotext.v1"
|
"gopkg.in/leonelquinteros/gotext.v1"
|
||||||
@ -53,10 +52,14 @@ type FSData struct {
|
|||||||
St *state.State
|
St *state.State
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FlagParserInterface interface {
|
||||||
|
GetFlag(key string) (uint32, error)
|
||||||
|
}
|
||||||
|
|
||||||
type Handlers struct {
|
type Handlers struct {
|
||||||
Alfred-mk marked this conversation as resolved
|
|||||||
fs *FSData
|
fs *FSData
|
||||||
db *gdbm.Database
|
db *gdbm.Database
|
||||||
parser *asm.FlagParser
|
parser FlagParserInterface
|
||||||
accountFileHandler utils.AccountFileHandlerInterface
|
accountFileHandler utils.AccountFileHandlerInterface
|
||||||
accountService server.AccountServiceInterface
|
accountService server.AccountServiceInterface
|
||||||
}
|
}
|
||||||
@ -107,8 +110,16 @@ func (h *Handlers) PreloadFlags(flagKeys []string) (map[string]uint32, error) {
|
|||||||
|
|
||||||
// SetLanguage sets the language across the menu
|
// SetLanguage sets the language across the menu
|
||||||
func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
inputStr := string(input)
|
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_language_set"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStr := string(input)
|
||||||
switch inputStr {
|
switch inputStr {
|
||||||
case "0":
|
case "0":
|
||||||
res.FlagSet = []uint32{state.FLAG_LANG}
|
res.FlagSet = []uint32{state.FLAG_LANG}
|
||||||
@ -119,7 +130,7 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_LANGUAGE_SET)
|
res.FlagSet = append(res.FlagSet, flags["flag_language_set"])
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
@ -130,7 +141,14 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r
|
|||||||
func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
err := h.accountFileHandler.EnsureFileExists()
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_account_created", "flag_account_creation_failed"}
|
||||||
Alfred-mk marked this conversation as resolved
Outdated
lash
commented
also seems unnecessary, there should be one single source of flag label to value map. also seems unnecessary, there should be one single source of flag label to value map.
Alfred-mk
commented
For clarity, do you mean that we should load all flags once in the menuhandler and have functions access the already loaded flags? For clarity, do you mean that we should load all flags once in the menuhandler and have functions access the already loaded flags?
lash
commented
yes, or perhaps even globally. yes, or perhaps even globally.
|
|||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.accountFileHandler.EnsureFileExists()
|
||||||
carlos marked this conversation as resolved
Outdated
lash
commented
please remove commented code if it is not of any more use please remove commented code if it is not of any more use
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@ -143,7 +161,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
|
|||||||
|
|
||||||
accountResp, err := h.accountService.CreateAccount()
|
accountResp, err := h.accountService.CreateAccount()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATION_FAILED)
|
res.FlagSet = append(res.FlagSet, flags["flag_account_creation_failed"])
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
data := map[string]string{
|
data := map[string]string{
|
||||||
@ -160,13 +178,19 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATED)
|
res.FlagSet = append(res.FlagSet, flags["flag_account_created"])
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SavePin persists the user's PIN choice into the filesystem
|
// SavePin persists the user's PIN choice into the filesystem
|
||||||
func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
flagKeys := []string{"flag_incorrect_pin"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
accountPIN := string(input)
|
accountPIN := string(input)
|
||||||
|
|
||||||
// accountData, err := h.accountFileHandler.ReadAccountData()
|
// accountData, err := h.accountFileHandler.ReadAccountData()
|
||||||
@ -176,11 +200,11 @@ func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resou
|
|||||||
|
|
||||||
// Validate that the PIN is a 4-digit number
|
// Validate that the PIN is a 4-digit number
|
||||||
if !isValidPIN(accountPIN) {
|
if !isValidPIN(accountPIN) {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTPIN)
|
res.FlagSet = append(res.FlagSet, flags["flag_incorrect_pin"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
|
res.FlagReset = append(res.FlagReset, flags["flag_incorrect_pin"])
|
||||||
//accountData["AccountPIN"] = accountPIN
|
//accountData["AccountPIN"] = accountPIN
|
||||||
|
|
||||||
key := []byte(AccountPin)
|
key := []byte(AccountPin)
|
||||||
@ -200,18 +224,26 @@ func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resou
|
|||||||
func (h *Handlers) SetResetSingleEdit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) SetResetSingleEdit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
menuOption := string(input)
|
menuOption := string(input)
|
||||||
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_allow_update", "flag_single_edit"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
switch menuOption {
|
switch menuOption {
|
||||||
case "2":
|
case "2":
|
||||||
res.FlagReset = append(res.FlagSet, models.USERFLAG_ALLOW_UPDATE)
|
res.FlagReset = append(res.FlagSet, flags["flag_allow_update"])
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_SINGLE_EDIT)
|
res.FlagSet = append(res.FlagSet, flags["flag_single_edit"])
|
||||||
case "3":
|
case "3":
|
||||||
res.FlagReset = append(res.FlagSet, models.USERFLAG_ALLOW_UPDATE)
|
res.FlagReset = append(res.FlagSet, flags["flag_allow_update"])
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_SINGLE_EDIT)
|
res.FlagSet = append(res.FlagSet, flags["flag_single_edit"])
|
||||||
case "4":
|
case "4":
|
||||||
res.FlagReset = append(res.FlagSet, models.USERFLAG_ALLOW_UPDATE)
|
res.FlagReset = append(res.FlagSet, flags["flag_allow_update"])
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_SINGLE_EDIT)
|
res.FlagSet = append(res.FlagSet, flags["flag_single_edit"])
|
||||||
default:
|
default:
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_SINGLE_EDIT)
|
res.FlagReset = append(res.FlagReset, flags["flag_single_edit"])
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
@ -222,20 +254,27 @@ func (h *Handlers) SetResetSingleEdit(ctx context.Context, sym string, input []b
|
|||||||
// to access the main menu
|
// to access the main menu
|
||||||
func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
pin, err := h.db.Fetch([]byte(AccountPin))
|
|
||||||
if err == nil {
|
// Preload the required flags
|
||||||
if bytes.Equal(input, pin) {
|
flagKeys := []string{"flag_valid_pin", "flag_pin_mismatch", "flag_pin_set"}
|
||||||
res.FlagSet = []uint32{models.USERFLAG_VALIDPIN}
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
res.FlagReset = []uint32{models.USERFLAG_PINMISMATCH}
|
if err != nil {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_PIN_SET)
|
|
||||||
} else {
|
|
||||||
res.FlagSet = []uint32{models.USERFLAG_PINMISMATCH}
|
|
||||||
}
|
|
||||||
} else if errors.Is(err, gdbm.ErrItemNotFound) {
|
|
||||||
//PIN not set yet
|
|
||||||
} else {
|
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accountData, err := h.accountFileHandler.ReadAccountData()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(input, []byte(accountData["AccountPIN"])) {
|
||||||
|
res.FlagSet = []uint32{flags["flag_valid_pin"]}
|
||||||
|
res.FlagReset = []uint32{flags["flag_pin_mismatch"]}
|
||||||
|
res.FlagSet = append(res.FlagSet, flags["flag_pin_set"])
|
||||||
|
} else {
|
||||||
|
res.FlagSet = []uint32{flags["flag_pin_mismatch"]}
|
||||||
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,14 +426,30 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte)
|
|||||||
// ResetAllowUpdate resets the allowupdate flag that allows a user to update profile data.
|
// ResetAllowUpdate resets the allowupdate flag that allows a user to update profile data.
|
||||||
func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ALLOW_UPDATE)
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_allow_update"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_allow_update"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetAccountAuthorized resets the account authorization flag after a successful PIN entry.
|
// 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) {
|
func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_AUTHORIZED)
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_account_authorized"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_account_authorized"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,12 +475,6 @@ func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte
|
|||||||
// It sets the required flags that control the flow.
|
// It sets the required flags that control the flow.
|
||||||
func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
//pin := string(input)
|
|
||||||
|
|
||||||
// accountData, err := h.accountFileHandler.ReadAccountData()
|
|
||||||
// if err != nil {
|
|
||||||
// return res, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Preload the required flags
|
// Preload the required flags
|
||||||
flagKeys := []string{"flag_incorrect_pin", "flag_account_authorized", "flag_allow_update"}
|
flagKeys := []string{"flag_incorrect_pin", "flag_account_authorized", "flag_allow_update"}
|
||||||
@ -434,6 +483,13 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pin := string(input)
|
||||||
|
|
||||||
|
accountData, err := h.accountFileHandler.ReadAccountData()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
storedpin, err := h.db.Fetch([]byte(AccountPin))
|
storedpin, err := h.db.Fetch([]byte(AccountPin))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if len(input) == 4 {
|
if len(input) == 4 {
|
||||||
@ -477,7 +533,15 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res
|
|||||||
// ResetIncorrectPin resets the incorrect pin flag after a new PIN attempt.
|
// 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) {
|
func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTPIN)
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_incorrect_pin"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_incorrect_pin"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,6 +550,21 @@ func (h *Handlers) ResetIncorrectPin(ctx context.Context, sym string, input []by
|
|||||||
func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flags
|
||||||
|
|
||||||
|
flagKeys := []string{"flag_account_success", "flag_account_pending"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_account_success", "flag_account_pending"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
// accountData, err := h.accountFileHandler.ReadAccountData()
|
// accountData, err := h.accountFileHandler.ReadAccountData()
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return res, err
|
// return res, err
|
||||||
@ -501,6 +580,7 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error checking account status:", err)
|
fmt.Println("Error checking account status:", err)
|
||||||
return res, err
|
return res, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//accountData["Status"] = status
|
//accountData["Status"] = status
|
||||||
@ -511,11 +591,11 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if status == "SUCCESS" {
|
if status == "SUCCESS" {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
|
res.FlagSet = append(res.FlagSet, flags["flag_account_success"])
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
|
res.FlagReset = append(res.FlagReset, flags["flag_account_pending"])
|
||||||
} else {
|
} else {
|
||||||
res.FlagReset = append(res.FlagSet, models.USERFLAG_ACCOUNT_SUCCESS)
|
res.FlagReset = append(res.FlagSet, flags["flag_account_success"])
|
||||||
res.FlagSet = append(res.FlagReset, models.USERFLAG_ACCOUNT_PENDING)
|
res.FlagSet = append(res.FlagReset, flags["flag_account_pending"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// err = h.accountFileHandler.WriteAccountData(accountData)
|
// err = h.accountFileHandler.WriteAccountData(accountData)
|
||||||
@ -530,30 +610,45 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
|
|||||||
func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) Quit(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_account_authorized"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
code := codeFromCtx(ctx)
|
code := codeFromCtx(ctx)
|
||||||
l := gotext.NewLocale(translationDir, code)
|
l := gotext.NewLocale(translationDir, code)
|
||||||
l.AddDomain("default")
|
l.AddDomain("default")
|
||||||
|
|
||||||
res.Content = l.Get("Thank you for using Sarafu. Goodbye!")
|
res.Content = l.Get("Thank you for using Sarafu. Goodbye!")
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_AUTHORIZED)
|
res.FlagReset = append(res.FlagReset, flags["flag_account_authorized"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyYob verifies the length of the given input
|
// VerifyYob verifies the length of the given input
|
||||||
func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
carlos marked this conversation as resolved
Outdated
lash
commented
we cannot have panics anywhere in the vm execution! Just return error. we cannot have panics anywhere in the vm execution! Just return error.
|
|||||||
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_incorrect_date_format"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
date := string(input)
|
date := string(input)
|
||||||
_, err := strconv.Atoi(date)
|
_, err = strconv.Atoi(date)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If conversion fails, input is not numeric
|
// If conversion fails, input is not numeric
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTDATEFORMAT)
|
res.FlagSet = append(res.FlagSet, flags["flag_incorrect_date_format"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(date) == 4 {
|
if len(date) == 4 {
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
|
res.FlagReset = append(res.FlagReset, flags["flag_incorrect_date_format"])
|
||||||
} else {
|
} else {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INCORRECTDATEFORMAT)
|
res.FlagSet = append(res.FlagSet, flags["flag_incorrect_date_format"])
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
@ -562,7 +657,15 @@ func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (res
|
|||||||
// ResetIncorrectYob resets the incorrect date format flag after a new attempt
|
// ResetIncorrectYob resets the incorrect date format flag after a new attempt
|
||||||
func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INCORRECTDATEFORMAT)
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_incorrect_date_format"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_incorrect_date_format"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,11 +691,19 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (
|
|||||||
// ValidateRecipient validates that the given input is a valid phone number.
|
// 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) {
|
func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
recipient := string(input)
|
||||||
|
|
||||||
|
accountData, err := h.accountFileHandler.ReadAccountData()
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
recipient := string(input)
|
recipient := string(input)
|
||||||
if recipient != "0" {
|
if recipient != "0" {
|
||||||
// mimic invalid number check
|
// mimic invalid number check
|
||||||
if recipient == "000" {
|
if recipient == "000" {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_RECIPIENT)
|
res.FlagSet = append(res.FlagSet, flags["flag_invalid_recipient"])
|
||||||
res.Content = recipient
|
res.Content = recipient
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
@ -612,6 +723,14 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by
|
|||||||
// as well as the invalid flags
|
// as well as the invalid flags
|
||||||
func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_invalid_recipient", "flag_invalid_recipient_with_invite"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
err := h.db.Delete([]byte(Amount))
|
err := h.db.Delete([]byte(Amount))
|
||||||
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -620,7 +739,8 @@ func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byt
|
|||||||
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_RECIPIENT, models.USERFLAG_INVALID_RECIPIENT_WITH_INVITE)
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_invalid_recipient"], flags["flag_invalid_recipient_with_invite"])
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
@ -628,11 +748,21 @@ func (h *Handlers) TransactionReset(ctx context.Context, sym string, input []byt
|
|||||||
// ResetTransactionAmount resets the transaction amount and invalid flag
|
// ResetTransactionAmount resets the transaction amount and invalid flag
|
||||||
func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) ResetTransactionAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_invalid_amount"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
err := h.db.Delete([]byte(Amount))
|
err := h.db.Delete([]byte(Amount))
|
||||||
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_INVALID_AMOUNT)
|
|
||||||
|
res.FlagReset = append(res.FlagReset, flags["flag_invalid_amount"])
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,13 +789,22 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res
|
|||||||
// it is not more than the current balance.
|
// it is not more than the current balance.
|
||||||
func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_invalid_amount"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
amountStr := string(input)
|
amountStr := string(input)
|
||||||
publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
|
publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
balanceStr, err := h.accountService.CheckBalance(string(publicKey))
|
balanceStr, err := h.accountService.CheckBalance(string(publicKey))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@ -685,20 +824,20 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
|
|||||||
re := regexp.MustCompile(`^(\d+(\.\d+)?)\s*(?:CELO)?$`)
|
re := regexp.MustCompile(`^(\d+(\.\d+)?)\s*(?:CELO)?$`)
|
||||||
matches := re.FindStringSubmatch(strings.TrimSpace(amountStr))
|
matches := re.FindStringSubmatch(strings.TrimSpace(amountStr))
|
||||||
if len(matches) < 2 {
|
if len(matches) < 2 {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
|
res.FlagSet = append(res.FlagSet, flags["flag_invalid_amount"])
|
||||||
res.Content = amountStr
|
res.Content = amountStr
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
inputAmount, err := strconv.ParseFloat(matches[1], 64)
|
inputAmount, err := strconv.ParseFloat(matches[1], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
|
res.FlagSet = append(res.FlagSet, flags["flag_invalid_amount"])
|
||||||
res.Content = amountStr
|
res.Content = amountStr
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if inputAmount > balanceValue {
|
if inputAmount > balanceValue {
|
||||||
res.FlagSet = append(res.FlagSet, models.USERFLAG_INVALID_AMOUNT)
|
res.FlagSet = append(res.FlagSet, flags["flag_invalid_amount"])
|
||||||
res.Content = amountStr
|
res.Content = amountStr
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
@ -795,6 +934,14 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res
|
|||||||
// gracefully exiting the session.
|
// gracefully exiting the session.
|
||||||
func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||||
res := resource.Result{}
|
res := resource.Result{}
|
||||||
|
|
||||||
|
// Preload the required flag
|
||||||
|
flagKeys := []string{"flag_account_authorized"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
code := codeFromCtx(ctx)
|
code := codeFromCtx(ctx)
|
||||||
l := gotext.NewLocale(translationDir, code)
|
l := gotext.NewLocale(translationDir, code)
|
||||||
l.AddDomain("default")
|
l.AddDomain("default")
|
||||||
@ -811,7 +958,7 @@ func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
res.Content = l.Get("Your account balance is %s", balance)
|
res.Content = l.Get("Your account balance is %s", balance)
|
||||||
res.FlagReset = append(res.FlagReset, models.USERFLAG_ACCOUNT_AUTHORIZED)
|
res.FlagReset = append(res.FlagReset, flags["flag_account_authorized"])
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,7 +969,12 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []
|
|||||||
code := codeFromCtx(ctx)
|
code := codeFromCtx(ctx)
|
||||||
l := gotext.NewLocale(translationDir, code)
|
l := gotext.NewLocale(translationDir, code)
|
||||||
l.AddDomain("default")
|
l.AddDomain("default")
|
||||||
|
// Preload the required flags
|
||||||
|
flagKeys := []string{"flag_invalid_recipient"}
|
||||||
|
flags, err := h.PreloadFlags(flagKeys)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
// TODO
|
// TODO
|
||||||
// Use the amount, recipient and sender to call the API and initialize the transaction
|
// Use the amount, recipient and sender to call the API and initialize the transaction
|
||||||
|
|
||||||
|
@ -21,6 +21,15 @@ type MockAccountService struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MockFlagParser struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockFlagParser) GetFlag(key string) (uint32, error) {
|
||||||
|
args := m.Called(key)
|
||||||
|
return args.Get(0).(uint32), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) {
|
func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) {
|
||||||
args := m.Called()
|
args := m.Called()
|
||||||
return args.Get(0).(*models.AccountResponse), args.Error(1)
|
return args.Get(0).(*models.AccountResponse), args.Error(1)
|
||||||
@ -70,11 +79,20 @@ func TestCreateAccount(t *testing.T) {
|
|||||||
// Set up expectations for the mock account service
|
// Set up expectations for the mock account service
|
||||||
mockAccountService.On("CreateAccount").Return(mockAccountResponse, nil)
|
mockAccountService.On("CreateAccount").Return(mockAccountResponse, nil)
|
||||||
|
|
||||||
|
mockParser := new(MockFlagParser)
|
||||||
|
|
||||||
|
flag_account_created := uint32(1)
|
||||||
|
flag_account_creation_failed := uint32(2)
|
||||||
|
|
||||||
|
mockParser.On("GetFlag", "flag_account_created").Return(flag_account_created, nil)
|
||||||
|
mockParser.On("GetFlag", "flag_account_creation_failed").Return(flag_account_creation_failed, nil)
|
||||||
|
|
||||||
// Initialize Handlers with mock account service
|
// Initialize Handlers with mock account service
|
||||||
h := &Handlers{
|
h := &Handlers{
|
||||||
fs: &FSData{Path: accountFilePath},
|
fs: &FSData{Path: accountFilePath},
|
||||||
accountFileHandler: accountFileHandler,
|
accountFileHandler: accountFileHandler,
|
||||||
accountService: mockAccountService,
|
accountService: mockAccountService,
|
||||||
|
parser: mockParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -87,7 +105,7 @@ func TestCreateAccount(t *testing.T) {
|
|||||||
name: "New account creation",
|
name: "New account creation",
|
||||||
existingData: nil,
|
existingData: nil,
|
||||||
expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
FlagSet: []uint32{models.USERFLAG_ACCOUNT_CREATED},
|
FlagSet: []uint32{flag_account_created},
|
||||||
},
|
},
|
||||||
expectedData: map[string]string{
|
expectedData: map[string]string{
|
||||||
"TrackingId": "test-tracking-id",
|
"TrackingId": "test-tracking-id",
|
||||||
@ -248,10 +266,16 @@ func TestSavePin(t *testing.T) {
|
|||||||
|
|
||||||
// Create a new AccountFileHandler and set it in the Handlers struct
|
// Create a new AccountFileHandler and set it in the Handlers struct
|
||||||
accountFileHandler := utils.NewAccountFileHandler(accountFilePath)
|
accountFileHandler := utils.NewAccountFileHandler(accountFilePath)
|
||||||
|
mockParser := new(MockFlagParser)
|
||||||
|
|
||||||
h := &Handlers{
|
h := &Handlers{
|
||||||
accountFileHandler: accountFileHandler,
|
accountFileHandler: accountFileHandler,
|
||||||
|
parser: mockParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flag_incorrect_pin := uint32(1)
|
||||||
|
mockParser.On("GetFlag", "flag_incorrect_pin").Return(flag_incorrect_pin, nil)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
input []byte
|
input []byte
|
||||||
@ -272,21 +296,21 @@ func TestSavePin(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Invalid PIN - non-numeric",
|
name: "Invalid PIN - non-numeric",
|
||||||
input: []byte("12ab"),
|
input: []byte("12ab"),
|
||||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
expectedFlags: []uint32{flag_incorrect_pin},
|
||||||
expectedData: initialAccountData, // No changes expected
|
expectedData: initialAccountData, // No changes expected
|
||||||
expectedErrors: false,
|
expectedErrors: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid PIN - less than 4 digits",
|
name: "Invalid PIN - less than 4 digits",
|
||||||
input: []byte("123"),
|
input: []byte("123"),
|
||||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
expectedFlags: []uint32{flag_incorrect_pin},
|
||||||
expectedData: initialAccountData, // No changes expected
|
expectedData: initialAccountData, // No changes expected
|
||||||
expectedErrors: false,
|
expectedErrors: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid PIN - more than 4 digits",
|
name: "Invalid PIN - more than 4 digits",
|
||||||
input: []byte("12345"),
|
input: []byte("12345"),
|
||||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
expectedFlags: []uint32{flag_incorrect_pin},
|
||||||
expectedData: initialAccountData, // No changes expected
|
expectedData: initialAccountData, // No changes expected
|
||||||
expectedErrors: false,
|
expectedErrors: false,
|
||||||
},
|
},
|
||||||
@ -294,7 +318,6 @@ func TestSavePin(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
// Ensure the file exists before running the test
|
|
||||||
err := accountFileHandler.EnsureFileExists()
|
err := accountFileHandler.EnsureFileExists()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to ensure account file exists: %v", err)
|
t.Fatalf("Failed to ensure account file exists: %v", err)
|
||||||
@ -906,12 +929,12 @@ func TestGetProfileInfo(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Profile with Not Provided Fields",
|
name: "Profile with Not Provided Fields",
|
||||||
accountData: map[string]string{
|
accountData: map[string]string{
|
||||||
"FirstName": "Not provided",
|
"FirstName": "Not provided",
|
||||||
"FamilyName": "Doe",
|
"FamilyName": "Doe",
|
||||||
"Gender": "Female",
|
"Gender": "Female",
|
||||||
"YOB": "1995",
|
"YOB": "1995",
|
||||||
"Location": "Not provided",
|
"Location": "Not provided",
|
||||||
"Offerings": "Service B",
|
"Offerings": "Service B",
|
||||||
},
|
},
|
||||||
readError: nil,
|
readError: nil,
|
||||||
expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
@ -925,12 +948,12 @@ func TestGetProfileInfo(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Profile with YOB as Not provided",
|
name: "Profile with YOB as Not provided",
|
||||||
accountData: map[string]string{
|
accountData: map[string]string{
|
||||||
"FirstName": "Not provided",
|
"FirstName": "Not provided",
|
||||||
"FamilyName": "Doe",
|
"FamilyName": "Doe",
|
||||||
"Gender": "Female",
|
"Gender": "Female",
|
||||||
"YOB": "Not provided",
|
"YOB": "Not provided",
|
||||||
"Location": "Not provided",
|
"Location": "Not provided",
|
||||||
"Offerings": "Service B",
|
"Offerings": "Service B",
|
||||||
},
|
},
|
||||||
readError: nil,
|
readError: nil,
|
||||||
expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
|
Loading…
Reference in New Issue
Block a user
I don't think mutex is needed here, it will be loaded once (before threads) and only read from then right?