Merge remote-tracking branch 'refs/remotes/origin/wip-flag-migration' into wip-flag-migration

This commit is contained in:
Carlosokumu 2024-09-02 16:30:58 +03:00
commit 626fca1a55
Signed by: carlos
GPG Key ID: 7BD6BC8160A5C953
2 changed files with 246 additions and 71 deletions

View File

@ -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 {
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"}
flags, err := h.PreloadFlags(flagKeys)
if err != nil {
return res, err
}
err = h.accountFileHandler.EnsureFileExists()
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{}
// 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

View File

@ -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)