Compare commits

..

4 Commits

Author SHA1 Message Date
lash
c4c3d6c998
Set upstream go-vise dependency version in go.mod 2024-09-07 21:14:03 +01:00
lash
4accb847b9
Successfully executed account regisration using http 2024-09-06 03:05:18 +01:00
lash
350b040a59
Add storage retrieval solution for http handler 2024-09-06 01:28:51 +01:00
lash
e6754a1e92
WIP http server harness 2024-09-06 00:40:57 +01:00
11 changed files with 1243 additions and 661 deletions

View File

@ -12,18 +12,18 @@ import (
fsdb "git.defalsify.org/vise.git/db/fs" fsdb "git.defalsify.org/vise.git/db/fs"
gdbmdb "git.defalsify.org/vise.git/db/gdbm" gdbmdb "git.defalsify.org/vise.git/db/gdbm"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/persist"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.defalsify.org/vise.git/logging"
"git.grassecon.net/urdt/ussd/internal/handlers/ussd" "git.grassecon.net/urdt/ussd/internal/handlers/ussd"
) )
var ( var (
logg = logging.NewVanilla() logg = logging.NewVanilla()
scriptDir = path.Join("services", "registration") scriptDir = path.Join("services", "registration")
) )
func getParser(fp string, debug bool) (*asm.FlagParser, error) { func getFlags(fp string, debug bool) (*asm.FlagParser, error) {
flagParser := asm.NewFlagParser().WithDebug() flagParser := asm.NewFlagParser().WithDebug()
_, err := flagParser.Load(fp) _, err := flagParser.Load(fp)
if err != nil { if err != nil {
@ -91,7 +91,7 @@ func getUserdataDb(dbDir string, ctx context.Context) db.Db {
store := gdbmdb.NewGdbmDb() store := gdbmdb.NewGdbmDb()
storeFile := path.Join(dbDir, "userdata.gdbm") storeFile := path.Join(dbDir, "userdata.gdbm")
store.Connect(ctx, storeFile) store.Connect(ctx, storeFile)
return store return store
} }
@ -113,21 +113,23 @@ func getEngine(cfg engine.Config, rs resource.Resource, pr *persist.Persister) *
func main() { func main() {
var dbDir string var dbDir string
var resourceDir string
var size uint var size uint
var sessionId string var sessionId string
var debug bool var debug bool
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from")
flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir")
flag.BoolVar(&debug, "d", false, "use engine debug output") flag.BoolVar(&debug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
flag.Parse() flag.Parse()
logg.Infof("start command", "dbdir", dbDir, "outputsize", size) logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size)
ctx := context.Background() ctx := context.Background()
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId",sessionId)
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
flagParser, err := getParser(pfp, true) flagParser, err := getFlags(pfp, true)
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)
@ -140,7 +142,7 @@ func main() {
FlagCount: uint32(16), FlagCount: uint32(16),
} }
rs, err := getResource(scriptDir, ctx) rs, err := getResource(resourceDir, ctx)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)

1
go-vise Submodule

@ -0,0 +1 @@
Subproject commit 2bddc363f20210ab019eec29d8ba4104d147e9b7

View File

@ -29,6 +29,23 @@ var (
translationDir = path.Join(scriptDir, "locale") translationDir = path.Join(scriptDir, "locale")
) )
const (
TrackingIdKey = "TRACKINGID"
PublicKeyKey = "PUBLICKEY"
CustodialIdKey = "CUSTODIALID"
AccountPin = "ACCOUNTPIN"
AccountStatus = "ACCOUNTSTATUS"
FirstName = "FIRSTNAME"
FamilyName = "FAMILYNAME"
YearOfBirth = "YOB"
Location = "LOCATION"
Gender = "GENDER"
Offerings = "OFFERINGS"
Recipient = "RECIPIENT"
Amount = "AMOUNT"
AccountCreated = "ACCOUNTCREATED"
)
type FSData struct { type FSData struct {
Path string Path string
St *state.State St *state.State
@ -58,24 +75,23 @@ func (fm *FlagManager) GetFlag(label string) (uint32, error) {
} }
type Handlers struct { type Handlers struct {
pe *persist.Persister pe *persist.Persister
st *state.State st *state.State
ca cache.Memory ca cache.Memory
userdataStore utils.DataStore userdataStore db.Db
flagManager *asm.FlagParser flagManager *asm.FlagParser
accountService server.AccountServiceInterface accountFileHandler *utils.AccountFileHandler
accountService server.AccountServiceInterface
} }
func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db) (*Handlers, error) { func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db) (*Handlers, error) {
if userdataStore == nil { if userdataStore == nil {
return nil, fmt.Errorf("cannot create handler with nil userdata store") return nil, fmt.Errorf("cannot create handler with nil userdata store")
} }
userDb := &utils.UserDataStore{
Db: userdataStore,
}
h := &Handlers{ h := &Handlers{
userdataStore: userDb, userdataStore: userdataStore,
flagManager: appFlags, flagManager: appFlags,
accountFileHandler: utils.NewAccountFileHandler(userdataStore),
accountService: &server.AccountService{}, accountService: &server.AccountService{},
} }
return h, nil return h, nil
@ -110,7 +126,7 @@ func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource
if h.st == nil || h.ca == nil { if h.st == nil || h.ca == nil {
logg.ErrorCtxf(ctx, "perister fail in handler", "state", h.st, "cache", h.ca) logg.ErrorCtxf(ctx, "perister fail in handler", "state", h.st, "cache", h.ca)
return r, fmt.Errorf("cannot get state and memory for handler") return r, fmt.Errorf("cannot get state and memory for handler")
} }
h.pe = nil h.pe = nil
logg.DebugCtxf(ctx, "handler has been initialized", "state", h.st, "cache", h.ca) logg.DebugCtxf(ctx, "handler has been initialized", "state", h.st, "cache", h.ca)
@ -152,8 +168,7 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r
} }
for key, value := range data { for key, value := range data {
store := h.userdataStore err := utils.WriteEntry(ctx, h.userdataStore, sessionId, key, []byte(value))
err := store.WriteEntry(ctx, sessionId, key, []byte(value))
if err != nil { if err != nil {
return err return err
} }
@ -170,15 +185,20 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, 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) {
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
store := h.userdataStore _, err = utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_CREATED)
_, err = store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_CREATED)
if err != nil { if err != nil {
if db.IsNotFound(err) { if db.IsNotFound(err) {
logg.Printf(logging.LVL_INFO, "Creating an account because it doesn't exist") fmt.Println("Creating an account because it doesn't exist")
err = h.createAccountNoExist(ctx, sessionId, &res)
if err != nil {
return res, err
}
} else {
err = h.createAccountNoExist(ctx, sessionId, &res) err = h.createAccountNoExist(ctx, sessionId, &res)
if err != nil { if err != nil {
return res, err return res, err
@ -192,7 +212,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
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) {
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
@ -208,18 +228,19 @@ func (h *Handlers) SavePin(ctx context.Context, sym string, input []byte) (resou
} }
res.FlagReset = append(res.FlagReset, flag_incorrect_pin) res.FlagReset = append(res.FlagReset, flag_incorrect_pin)
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN)) err = utils.WriteEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN, []byte(accountPIN))
if err != nil { if err != nil {
return res, err return res, nil
} }
return res, nil return res, nil
} }
// SetResetSingleEdit sets and resets flags to allow gradual editing of profile information. // SetResetSingleEdit sets and resets flags to allow gradual editing of profile information.
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) {
var res resource.Result var res resource.Result
menuOption := string(input) menuOption := string(input)
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
@ -257,12 +278,7 @@ func (h *Handlers) VerifyPin(ctx context.Context, sym string, input []byte) (res
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
//AccountPin, _ := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN) AccountPin, _ := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN)
store := h.userdataStore
AccountPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN)
if err != nil {
return res, err
}
if bytes.Equal(input, AccountPin) { if bytes.Equal(input, AccountPin) {
res.FlagSet = []uint32{flag_valid_pin} res.FlagSet = []uint32{flag_valid_pin}
@ -285,103 +301,67 @@ func codeFromCtx(ctx context.Context) string {
return code return code
} }
// SaveFirstname updates the first name in the gdbm with the provided input. // SaveFirstname updates the first name in a JSON data file with the provided input.
func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 { if len(input) > 0 {
firstName := string(input) //name := string(input)
store := h.userdataStore //key := []byte(FirstName)
err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) //value := []byte(name)
if err != nil { //h.db.Store(key, value, true)
return res, err
}
} }
return res, nil return res, nil
} }
// SaveFamilyname updates the family name in the gdbm with the provided input. // SaveFamilyname updates the family name in a JSON data file with the provided input.
func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 { if len(input) > 0 {
familyName := string(input) //secondname := string(input)
store := h.userdataStore //key := []byte(FamilyName)
err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) //value := []byte(secondname)
if err != nil { //h.db.Store(key, value, true)
return res, err
}
if err != nil {
return res, nil
}
} else {
return res, fmt.Errorf("a family name cannot be less than one character")
} }
return res, nil return res, nil
} }
// SaveYOB updates the Year of Birth(YOB) in the gdbm with the provided input. // SaveYOB updates the Year of Birth(YOB) in a JSON data file with the provided input.
func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) == 4 { yob := string(input)
yob := string(input) if len(yob) == 4 {
store := h.userdataStore //yob := string(input)
err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(yob)) //key := []byte(YearOfBirth)
if err != nil { //value := []byte(yob)
return res, err //h.db.Store(key, value, true)
}
} }
return res, nil return res, nil
} }
// SaveLocation updates the location in the gdbm with the provided input. // SaveLocation updates the location in a JSON data file with the provided input.
func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 { if len(input) > 0 {
location := string(input) //location := string(input)
store := h.userdataStore //key := []byte(Location)
err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) //value := []byte(location)
if err != nil {
return res, err //h.db.Store(key, value, true)
}
} }
return res, nil return res, nil
} }
// SaveGender updates the gender in the gdbm with the provided input. // SaveGender updates the gender in a JSON data file with the provided input.
func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 { if len(input) > 0 {
gender := string(input) gender := string(input)
@ -393,34 +373,23 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re
case "3": case "3":
gender = "Unspecified" gender = "Unspecified"
} }
store := h.userdataStore //key := []byte(Gender)
err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) //value := []byte(gender)
if err != nil { //h.db.Store(key, value, true)
return res, nil
}
} }
return res, nil return res, nil
} }
// SaveOfferings updates the offerings(goods and services provided by the user) in the gdbm with the provided input. // SaveOfferings updates the offerings(goods and services provided by the user) in a JSON data file with the provided input.
func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 { if len(input) > 0 {
offerings := string(input) //offerings := string(input)
store := h.userdataStore //key := []byte(Offerings)
err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(offerings)) //value := []byte(offerings)
if err != nil { //h.db.Store(key, value, true)
return res, nil
}
} }
return res, nil return res, nil
} }
@ -448,16 +417,11 @@ func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input
func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string) //publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
if !ok { // if err != nil {
return res, fmt.Errorf("missing session") // return res, err
} // }
res.Content = "string(publicKey)"
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
res.Content = string(publicKey)
return res, nil return res, nil
} }
@ -467,20 +431,14 @@ func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (res
var res resource.Result var res resource.Result
var err error var err error
flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin")
flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized")
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
AccountPin, err := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_ACCOUNT_PIN)
flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin")
flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized")
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
store := h.userdataStore
AccountPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_ACCOUNT_PIN)
if err != nil {
return res, err
}
if err == nil { if err == nil {
if len(input) == 4 { if len(input) == 4 {
@ -527,22 +485,26 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
store := h.userdataStore
trackingId, err := store.ReadEntry(ctx, sessionId, utils.DATA_TRACKING_ID) trackingId, _ := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_TRACKING_ID)
if err != nil {
return res, err
}
status, err := h.accountService.CheckAccountStatus(string(trackingId)) status, err := h.accountService.CheckAccountStatus(string(trackingId))
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
} }
err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)) // err = h.db.Store(toBytes(AccountStatus), toBytes(status), true)
if err != nil { // if err != nil {
return res, nil // return res, nil
} // }
// err = h.db.Store(toBytes(TrackingIdKey), toBytes(status), true)
// if err != nil {
// return res, nil
// }
if status == "SUCCESS" { if status == "SUCCESS" {
res.FlagSet = append(res.FlagSet, flag_account_success) res.FlagSet = append(res.FlagSet, flag_account_success)
@ -609,16 +571,14 @@ func (h *Handlers) CheckBalance(ctx context.Context, sym string, input []byte) (
var res resource.Result var res resource.Result
var err error var err error
// publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
store := h.userdataStore publicKey, _ := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_PUBLIC_KEY)
publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
if err != nil {
return res, err
}
balance, err := h.accountService.CheckBalance(string(publicKey)) balance, err := h.accountService.CheckBalance(string(publicKey))
if err != nil { if err != nil {
@ -632,12 +592,6 @@ 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) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
recipient := string(input) recipient := string(input)
@ -651,11 +605,12 @@ func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []by
return res, nil return res, nil
} }
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte(recipient)) // accountData["Recipient"] = recipient
if err != nil { // key := []byte(Recipient)
return res, nil // value := []byte(recipient)
}
// h.db.Store(key, value, true)
} }
return res, nil return res, nil
@ -665,25 +620,18 @@ 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) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient")
flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite")
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(""))
if err != nil {
return res, nil
}
err = store.WriteEntry(ctx, sessionId, utils.DATA_RECIPIENT, []byte("")) // err := h.db.Delete([]byte(Amount))
if err != nil { // if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
return res, nil // return res, err
} // }
// err = h.db.Delete([]byte(Recipient))
// if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
// return res, err
// }
res.FlagReset = append(res.FlagReset, flag_invalid_recipient, flag_invalid_recipient_with_invite) res.FlagReset = append(res.FlagReset, flag_invalid_recipient, flag_invalid_recipient_with_invite)
@ -693,19 +641,13 @@ 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) {
var res resource.Result var res resource.Result
var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount")
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte("")) // err := h.db.Delete([]byte(Amount))
if err != nil { // if err != nil && !errors.Is(err, gdbm.ErrItemNotFound) {
return res, nil // return res, err
} // }
res.FlagReset = append(res.FlagReset, flag_invalid_amount) res.FlagReset = append(res.FlagReset, flag_invalid_amount)
@ -718,14 +660,12 @@ func (h *Handlers) MaxAmount(ctx context.Context, sym string, input []byte) (res
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string) // publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
if !ok { // if err != nil {
return res, fmt.Errorf("missing session") // return res, err
} // }
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
balance, err := h.accountService.CheckBalance(string(publicKey)) balance, err := h.accountService.CheckBalance(string("publicKey"))
if err != nil { if err != nil {
return res, nil return res, nil
} }
@ -741,18 +681,16 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount") flag_invalid_amount, _ := h.flagManager.GetFlag("flag_invalid_amount")
publicKey, _ := utils.ReadEntry(ctx, h.userdataStore, sessionId, utils.DATA_PUBLIC_KEY)
amountStr := string(input) amountStr := string(input)
// publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
balanceStr, err := h.accountService.CheckBalance(string(publicKey)) // if err != nil {
// return res, err
// }
balanceStr, err := h.accountService.CheckBalance(string("publicKey"))
if err != nil { if err != nil {
return res, err return res, err
@ -792,8 +730,10 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
} }
res.Content = fmt.Sprintf("%.3f", inputAmount) // Format to 3 decimal places res.Content = fmt.Sprintf("%.3f", inputAmount) // Format to 3 decimal places
store := h.userdataStore // key := []byte(Amount)
err = store.WriteEntry(ctx, sessionId, utils.DATA_AMOUNT, []byte(amountStr)) // value := []byte(res.Content)
// h.db.Store(key, value, true)
if err != nil { if err != nil {
return res, err return res, err
} }
@ -801,18 +741,16 @@ func (h *Handlers) ValidateAmount(ctx context.Context, sym string, input []byte)
return res, nil return res, nil
} }
// GetRecipient returns the transaction recipient from the gdbm. // GetRecipient returns the transaction recipient from a JSON data file.
func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string) // recipient, err := h.db.Fetch([]byte(Recipient))
if !ok { // if err != nil {
return res, fmt.Errorf("missing session") // return res, err
} // }
store := h.userdataStore
recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT)
res.Content = string(recipient) res.Content = string("recipient")
return res, nil return res, nil
} }
@ -821,15 +759,12 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (
func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string) // publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
if !ok { // if err != nil {
return res, fmt.Errorf("missing session") // return res, err
} // }
store := h.userdataStore res.Content = string("publicKey")
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
res.Content = string(publicKey)
return res, nil return res, nil
} }
@ -838,14 +773,11 @@ func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (res
func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string) // amount, err := h.db.Fetch([]byte(Amount))
if !ok { // if err != nil {
return res, fmt.Errorf("missing session") // return res, err
} // }
store := h.userdataStore res.Content = string("amount")
amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT)
res.Content = string(amount)
return res, nil return res, nil
} }
@ -855,23 +787,17 @@ func (h *Handlers) GetAmount(ctx context.Context, sym string, input []byte) (res
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) {
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized")
code := codeFromCtx(ctx) code := codeFromCtx(ctx)
l := gotext.NewLocale(translationDir, code) l := gotext.NewLocale(translationDir, code)
l.AddDomain("default") l.AddDomain("default")
// publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
store := h.userdataStore // if err != nil {
publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) // return res, err
if err != nil { // }
return res, err balance, err := h.accountService.CheckBalance(string("publicKey"))
}
balance, err := h.accountService.CheckBalance(string(publicKey))
if err != nil { if err != nil {
return res, nil return res, nil
} }
@ -881,28 +807,31 @@ func (h *Handlers) QuitWithBalance(ctx context.Context, sym string, input []byte
} }
// InitiateTransaction returns a confirmation and resets the transaction data // InitiateTransaction returns a confirmation and resets the transaction data
// on the gdbm store. // on the JSON file.
func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var err error var err error
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
code := codeFromCtx(ctx) code := codeFromCtx(ctx)
l := gotext.NewLocale(translationDir, code) l := gotext.NewLocale(translationDir, code)
l.AddDomain("default") l.AddDomain("default")
// 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
store := h.userdataStore
publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
amount, _ := store.ReadEntry(ctx, sessionId, utils.DATA_AMOUNT) // publicKey, err := h.db.Fetch([]byte(PublicKeyKey))
// if err != nil {
// return res, err
// }
// amount, err := h.db.Fetch([]byte(Amount))
// if err != nil {
// return res, err
// }
// recipient, err := h.db.Fetch([]byte(Recipient))
// if err != nil {
// return res, err
// }
recipient, _ := store.ReadEntry(ctx, sessionId, utils.DATA_RECIPIENT) //res.Content = l.Get("Your request has been sent. %s will receive %s from %s.", string(recipient), string(amount), string(publicKey))
res.Content = l.Get("Your request has been sent. %s will receive %s from %s.", string(recipient), string(amount), string(publicKey))
account_authorized_flag, err := h.flagManager.GetFlag("flag_account_authorized") account_authorized_flag, err := h.flagManager.GetFlag("flag_account_authorized")
if err != nil { if err != nil {
@ -916,55 +845,62 @@ func (h *Handlers) InitiateTransaction(ctx context.Context, sym string, input []
// GetProfileInfo retrieves and formats the profile information of a user from a Gdbm backed storage. // GetProfileInfo retrieves and formats the profile information of a user from a Gdbm backed storage.
func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *Handlers) GetProfileInfo(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return res, fmt.Errorf("missing session")
}
// Default value when an entry is not found // Define default values
defaultValue := "Not Provided" defaultValue := "Not provided"
name := defaultValue
familyName := defaultValue
yob := defaultValue
gender := defaultValue
location := defaultValue
offerings := defaultValue
// Helper function to handle nil byte slices and convert them to string // Fetch data using a map for better organization
getEntryOrDefault := func(entry []byte, err error) string { // dataKeys := map[string]*string{
if err != nil || entry == nil { // FirstName: &name,
return defaultValue // FamilyName: &familyName,
} // YearOfBirth: &yob,
return string(entry) // Location: &location,
} // Gender: &gender,
store := h.userdataStore // Offerings: &offerings,
// Retrieve user data as strings with fallback to defaultValue // }
firstName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FIRST_NAME))
familyName := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_FAMILY_NAME)) // Iterate over keys and fetch values
yob := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_YOB)) //iter := h.db.Iterator()
gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_GENDER)) // next := h.db.Iterator()
location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_LOCATION)) // //defer iter.Close() // Ensure the iterator is closed
offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, utils.DATA_OFFERINGS)) // for key, err := next(); err == nil; key, err = next() {
// if valuePointer, ok := dataKeys[string(key)]; ok {
// // value, fetchErr := h.db.Fetch(key)
// // if fetchErr == nil {
// // *valuePointer = string(value)
// // }
// }
// }
// Construct the full name // Construct the full name
name := defaultValue
if familyName != defaultValue { if familyName != defaultValue {
if firstName == defaultValue { if name == defaultValue {
name = familyName name = familyName
} else { } else {
name = firstName + " " + familyName name = name + " " + familyName
} }
} }
// Calculate age from year of birth // Calculate age from year of birth
age := defaultValue var age string
if yob != defaultValue { if yob != defaultValue {
if yobInt, err := strconv.Atoi(yob); err == nil { yobInt, err := strconv.Atoi(yob)
age = strconv.Itoa(utils.CalculateAgeWithYOB(yobInt)) if err != nil {
} else {
return res, fmt.Errorf("invalid year of birth: %v", err) return res, fmt.Errorf("invalid year of birth: %v", err)
} }
age = strconv.Itoa(utils.CalculateAgeWithYOB(yobInt))
} else {
age = defaultValue
} }
// Format the result // Format the result
res.Content = fmt.Sprintf( formattedData := fmt.Sprintf("Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\n", name, gender, age, location, offerings)
"Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\n", res.Content = formattedData
name, gender, age, location, offerings,
)
return res, nil return res, nil
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,59 +0,0 @@
package mocks
import (
"context"
"git.defalsify.org/vise.git/lang"
"github.com/stretchr/testify/mock"
)
type MockDb struct {
mock.Mock
}
func (m *MockDb) SetPrefix(prefix uint8) {
m.Called(prefix)
}
func (m *MockDb) Prefix() uint8 {
args := m.Called()
return args.Get(0).(uint8)
}
func (m *MockDb) Safe() bool {
args := m.Called()
return args.Get(0).(bool)
}
func (m *MockDb) SetLanguage(language *lang.Language) {
m.Called(language)
}
func (m *MockDb) SetLock(uint8, bool) error {
args := m.Called()
return args.Error(0)
}
func (m *MockDb) Connect(ctx context.Context, connectionStr string) error {
args := m.Called(ctx, connectionStr)
return args.Error(0)
}
func (m *MockDb) SetSession(sessionId string) {
m.Called(sessionId)
}
func (m *MockDb) Put(ctx context.Context, key, value []byte) error {
args := m.Called(ctx, key, value)
return args.Error(0)
}
func (m *MockDb) Get(ctx context.Context, key []byte) ([]byte, error) {
args := m.Called(ctx, key)
return nil, args.Error(0)
}
func (m *MockDb) Close() error {
args := m.Called(nil)
return args.Error(0)
}

View File

@ -0,0 +1,44 @@
package mocks
import (
"git.grassecon.net/urdt/ussd/internal/models"
"github.com/stretchr/testify/mock"
)
type MockAccountFileHandler struct {
mock.Mock
}
func (m *MockAccountFileHandler) EnsureFileExists() error {
args := m.Called()
return args.Error(0)
}
func (m *MockAccountFileHandler) ReadAccountData() (map[string]string, error) {
args := m.Called()
return args.Get(0).(map[string]string), args.Error(1)
}
func (m *MockAccountFileHandler) WriteAccountData(data map[string]string) error {
args := m.Called(data)
return args.Error(0)
}
type MockAccountService struct {
mock.Mock
}
func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) {
args := m.Called()
return args.Get(0).(*models.AccountResponse), args.Error(1)
}
func (m *MockAccountService) CheckAccountStatus(TrackingId string) (string, error) {
args := m.Called()
return args.Get(0).(string), args.Error(1)
}
func (m *MockAccountService) CheckBalance(PublicKey string) (string, error) {
args := m.Called()
return args.Get(0).(string), args.Error(1)
}

View File

@ -1,26 +0,0 @@
package mocks
import (
"git.grassecon.net/urdt/ussd/internal/models"
"github.com/stretchr/testify/mock"
)
// MockAccountService implements AccountServiceInterface for testing
type MockAccountService struct {
mock.Mock
}
func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) {
args := m.Called()
return args.Get(0).(*models.AccountResponse), args.Error(1)
}
func (m *MockAccountService) CheckBalance(publicKey string) (string, error) {
args := m.Called(publicKey)
return args.String(0), args.Error(1)
}
func (m *MockAccountService) CheckAccountStatus(trackingId string) (string, error) {
args := m.Called(trackingId)
return args.String(0), args.Error(1)
}

View File

@ -1,24 +0,0 @@
package mocks
import (
"context"
"git.defalsify.org/vise.git/db"
"git.grassecon.net/urdt/ussd/internal/utils"
"github.com/stretchr/testify/mock"
)
type MockUserDataStore struct {
db.Db
mock.Mock
}
func (m *MockUserDataStore) ReadEntry(ctx context.Context, sessionId string, typ utils.DataTyp) ([]byte, error) {
args := m.Called(ctx, sessionId, typ)
return args.Get(0).([]byte), args.Error(1)
}
func (m *MockUserDataStore) WriteEntry(ctx context.Context, sessionId string, typ utils.DataTyp, value []byte) error {
args := m.Called(ctx, sessionId, typ, value)
return args.Error(0)
}

View File

@ -0,0 +1,77 @@
package utils
import (
"context"
"encoding/json"
"git.defalsify.org/vise.git/db"
)
type AccountFileHandler struct {
//FilePath string
store db.Db
}
// func NewAccountFileHandler(path string) *AccountFileHandler {
// return &AccountFileHandler{FilePath: path}
// }
func NewAccountFileHandler(store db.Db) *AccountFileHandler {
return &AccountFileHandler{
store: store,
}
}
// func (afh *AccountFileHandler) ReadAccountData() (map[string]string, error) {
// jsonData, err := os.ReadFile(afh.FilePath)
// if err != nil {
// return nil, err
// }
// var accountData map[string]string
// err = json.Unmarshal(jsonData, &accountData)
// if err != nil {
// return nil, err
// }
// return accountData, nil
// }
func (afh *AccountFileHandler) ReadAccountData(ctx context.Context, sessionId string) (map[string]string, error) {
var accountData map[string]string
jsonData, err := ReadEntry(ctx, afh.store, sessionId, DATA_ACCOUNT)
err = json.Unmarshal(jsonData, &accountData)
if err != nil {
return nil, err
}
return accountData, nil
}
// func (afh *AccountFileHandler) WriteAccountData(accountData map[string]string) error {
// jsonData, err := json.Marshal(accountData)
// if err != nil {
// return err
// }
// return os.WriteFile(afh.FilePath, jsonData, 0644)
// }
func (afh *AccountFileHandler) WriteAccountData(ctx context.Context, sessionId string, accountData map[string]string) error {
_, err := json.Marshal(accountData)
if err != nil {
return err
}
return nil
}
// func (afh *AccountFileHandler) EnsureFileExists() error {
// f, err := os.OpenFile(afh.FilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// if err != nil {
// return err
// }
// return f.Close()
// }
func (afh *AccountFileHandler) EnsureFileExists() error {
return nil
}

View File

@ -16,15 +16,6 @@ const (
DATA_PUBLIC_KEY DATA_PUBLIC_KEY
DATA_CUSTODIAL_ID DATA_CUSTODIAL_ID
DATA_ACCOUNT_PIN DATA_ACCOUNT_PIN
DATA_ACCOUNT_STATUS
DATA_FIRST_NAME
DATA_FAMILY_NAME
DATA_YOB
DATA_LOCATION
DATA_GENDER
DATA_OFFERINGS
DATA_RECIPIENT
DATA_AMOUNT
) )
func typToBytes(typ DataTyp) []byte { func typToBytes(typ DataTyp) []byte {
@ -33,16 +24,15 @@ func typToBytes(typ DataTyp) []byte {
return b[:] return b[:]
} }
func PackKey(typ DataTyp, data []byte) []byte { func packKey(typ DataTyp, data []byte) []byte {
v := typToBytes(typ) v := typToBytes(typ)
return append(v, data...) return append(v, data...)
} }
func ReadEntry(ctx context.Context, store db.Db, sessionId string, typ DataTyp) ([]byte, error) { func ReadEntry(ctx context.Context, store db.Db, sessionId string, typ DataTyp) ([]byte, error) {
store.SetPrefix(db.DATATYPE_USERDATA) store.SetPrefix(db.DATATYPE_USERDATA)
store.SetSession(sessionId) store.SetSession(sessionId)
k := PackKey(typ, []byte(sessionId)) k := packKey(typ, []byte(sessionId))
b, err := store.Get(ctx, k) b, err := store.Get(ctx, k)
if err != nil { if err != nil {
return nil, err return nil, err
@ -53,6 +43,6 @@ func ReadEntry(ctx context.Context, store db.Db, sessionId string, typ DataTyp)
func WriteEntry(ctx context.Context, store db.Db, sessionId string, typ DataTyp, value []byte) error { func WriteEntry(ctx context.Context, store db.Db, sessionId string, typ DataTyp, value []byte) error {
store.SetPrefix(db.DATATYPE_USERDATA) store.SetPrefix(db.DATATYPE_USERDATA)
store.SetSession(sessionId) store.SetSession(sessionId)
k := PackKey(typ, []byte(sessionId)) k := packKey(typ, []byte(sessionId))
return store.Put(ctx, k, value) return store.Put(ctx, k, value)
} }

View File

@ -1,32 +0,0 @@
package utils
import (
"context"
"git.defalsify.org/vise.git/db"
)
type DataStore interface {
db.Db
ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error)
WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error
}
type UserDataStore struct {
db.Db
}
// ReadEntry retrieves an entry from the store based on the provided parameters.
func (store *UserDataStore) ReadEntry(ctx context.Context, sessionId string, typ DataTyp) ([]byte, error) {
store.SetPrefix(db.DATATYPE_USERDATA)
store.SetSession(sessionId)
k := PackKey(typ, []byte(sessionId))
return store.Get(ctx, k)
}
func (store *UserDataStore) WriteEntry(ctx context.Context, sessionId string, typ DataTyp, value []byte) error {
store.SetPrefix(db.DATATYPE_USERDATA)
store.SetSession(sessionId)
k := PackKey(typ, []byte(sessionId))
return store.Put(ctx, k, value)
}