Compare commits
31 Commits
lash/event
...
data-migra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbfd81c94e
|
||
|
|
bad273fa58
|
||
|
|
ccd9e9cd77 | ||
| 71ff251d51 | |||
|
|
4cc0de59a7
|
||
|
|
4b8505680b
|
||
|
|
104db94826
|
||
|
|
ecee5b4dee
|
||
|
|
879baa03fc
|
||
|
|
ecac4ae009 | ||
|
|
6b404f56c9
|
||
| ca7dc6779a | |||
|
|
471bbea5ca
|
||
|
|
78fae3526b
|
||
|
|
cf27479fcf
|
||
|
|
799d1a51fa
|
||
|
|
1376c7b8dd
|
||
|
|
e410158432
|
||
|
|
b70d6b54d1 | ||
|
|
46544b723b
|
||
|
|
ff06b92ffd
|
||
| 0a7152d6b8 | |||
|
|
47da078244 | ||
| acfb6c1d76 | |||
|
|
f8b38dd210
|
||
|
|
ac492e8403
|
||
|
|
ac00e4619e
|
||
|
|
604f3103c7
|
||
|
|
26b32a8b93
|
||
|
|
960a3d9075
|
||
|
|
55356a0c64
|
@@ -22,9 +22,8 @@ import (
|
||||
|
||||
at "git.grassecon.net/grassrootseconomics/visedriver-africastalking/africastalking"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
|
||||
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -121,7 +120,8 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
accountService := &httpremote.HTTPAccountService{}
|
||||
accountService := services.New(ctx, menuStorageService, connData)
|
||||
|
||||
hl, err := lhs.GetHandler(accountService)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "httpaccountservice: %v\n", err)
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/request"
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
|
||||
)
|
||||
@@ -125,7 +125,8 @@ func main() {
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userdataStore)
|
||||
accountService := &httpremote.HTTPAccountService{}
|
||||
|
||||
accountService := services.New(ctx, menuStorageService, connData)
|
||||
|
||||
hl, err := lhs.GetHandler(accountService)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/request"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
|
||||
)
|
||||
@@ -116,7 +116,8 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
accountService := &httpremote.HTTPAccountService{}
|
||||
accountService := services.New(ctx, menuStorageService, connData)
|
||||
|
||||
hl, err := lhs.GetHandler(accountService)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
@@ -130,6 +131,8 @@ func main() {
|
||||
}
|
||||
defer stateStore.Close()
|
||||
|
||||
//accountService := services.New(ctx, menuStorageService, connData)
|
||||
|
||||
rp := &httprequest.DefaultRequestParser{}
|
||||
bsh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl)
|
||||
sh := httprequest.NewHTTPRequestHandler(bsh)
|
||||
|
||||
48
cmd/main.go
48
cmd/main.go
@@ -13,13 +13,9 @@ import (
|
||||
"git.defalsify.org/vise.git/lang"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
devremote "git.grassecon.net/grassrootseconomics/sarafu-api/dev"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/event"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -28,37 +24,9 @@ var (
|
||||
menuSeparator = ": "
|
||||
)
|
||||
|
||||
type devEmitter struct {
|
||||
h *apievent.EventsHandler
|
||||
}
|
||||
|
||||
func (d *devEmitter) emit(ctx context.Context, msg apievent.Msg) error {
|
||||
var err error
|
||||
if msg.Typ == apievent.EventTokenTransferTag {
|
||||
tx, ok := msg.Item.(devremote.Tx)
|
||||
if !ok {
|
||||
return fmt.Errorf("not a valid tx")
|
||||
}
|
||||
logg.InfoCtxf(ctx, "tx emit", "tx", tx)
|
||||
ev := tx.ToTransferEvent()
|
||||
err = d.h.Handle(ctx, apievent.EventTokenTransferTag, &ev)
|
||||
} else if msg.Typ == apievent.EventRegistrationTag {
|
||||
acc, ok := msg.Item.(devremote.Account)
|
||||
if !ok {
|
||||
return fmt.Errorf("not a valid tx")
|
||||
}
|
||||
logg.InfoCtxf(ctx, "account emit", "account", acc)
|
||||
ev := acc.ToRegistrationEvent()
|
||||
err = d.h.Handle(ctx, apievent.EventRegistrationTag, &ev)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
config.LoadConfig()
|
||||
|
||||
var accountService remote.AccountService
|
||||
var fakeDir string
|
||||
var connStr string
|
||||
var size uint
|
||||
var sessionId string
|
||||
@@ -71,7 +39,6 @@ func main() {
|
||||
flag.StringVar(&resourceDir, "resourcedir", scriptDir, "resource dir")
|
||||
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
|
||||
flag.StringVar(&connStr, "c", "", "connection string")
|
||||
flag.StringVar(&fakeDir, "fakedir", "", "if valid path, enables fake api with fsdb backend")
|
||||
flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
|
||||
flag.UintVar(&size, "s", 160, "max size of output")
|
||||
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
|
||||
@@ -155,18 +122,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if fakeDir != "" {
|
||||
svc := devremote.NewDevAccountService(ctx, fakeDir).WithAutoVoucher(ctx, "FOO", 42)
|
||||
eu := event.NewEventsUpdater(svc, menuStorageService)
|
||||
emitter := &devEmitter{
|
||||
h: eu.ToEventsHandler(),
|
||||
}
|
||||
svc = svc.WithEmitter(emitter.emit)
|
||||
svc.AddVoucher(ctx, "BAR")
|
||||
accountService = svc
|
||||
} else {
|
||||
accountService = &httpremote.HTTPAccountService{}
|
||||
}
|
||||
accountService := services.New(ctx, menuStorageService, connData)
|
||||
hl, err := lhs.GetHandler(accountService)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err)
|
||||
|
||||
@@ -86,7 +86,7 @@ func main() {
|
||||
cfg := engine.Config{
|
||||
Root: "root",
|
||||
OutputSize: uint32(size),
|
||||
FlagCount: uint32(16),
|
||||
FlagCount: uint32(128),
|
||||
}
|
||||
if stateDebug {
|
||||
cfg.StateDebug = true
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"admins": [
|
||||
{
|
||||
"phonenumber" : "<replace with any admin number to test with >"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
|
||||
)
|
||||
|
||||
var (
|
||||
logg = logging.NewVanilla().WithDomain("adminstore")
|
||||
)
|
||||
|
||||
type Admin struct {
|
||||
PhoneNumber string `json:"phonenumber"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Admins []Admin `json:"admins"`
|
||||
}
|
||||
|
||||
func Seed(ctx context.Context) error {
|
||||
var config Config
|
||||
adminstore, err := store.NewAdminStore(ctx, "../admin_numbers")
|
||||
store := adminstore.FsStore
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.Close()
|
||||
data, err := os.ReadFile("admin_numbers.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, admin := range config.Admins {
|
||||
err := store.Put(ctx, []byte(admin.PhoneNumber), []byte("1"))
|
||||
if err != nil {
|
||||
logg.Printf(logging.LVL_DEBUG, "Failed to insert admin number", admin.PhoneNumber)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2,16 +2,72 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/devtools/admin/commands"
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/internal/cmd"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
|
||||
)
|
||||
|
||||
var (
|
||||
logg = logging.NewVanilla().WithContextKey("SessionId")
|
||||
scriptDir = path.Join("services", "registration")
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
err := commands.Seed(ctx)
|
||||
config.LoadConfig()
|
||||
|
||||
var sessionId string
|
||||
var connStr string
|
||||
|
||||
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
|
||||
flag.StringVar(&connStr, "c", "", "connection string")
|
||||
flag.Parse()
|
||||
|
||||
|
||||
if connStr == "" {
|
||||
connStr = config.DbConn()
|
||||
}
|
||||
connData, err := storage.ToConnData(connStr)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize a list of admins with error %s", err)
|
||||
fmt.Fprintf(os.Stderr, "connstr err: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
|
||||
pfp := path.Join(scriptDir, "pp.csv")
|
||||
flagParser, err := application.NewFlagManager(pfp)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "flagparser fail: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
x := cmd.NewCmd(connData, sessionId, flagParser)
|
||||
err = x.Parse(flag.Args())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "cmd parse fail: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logg.Infof("start command", "conn", connData, "subcmd", x)
|
||||
|
||||
menuStorageService := storage.NewMenuStorageService(connData, "")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "menu storage service error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = x.Exec(ctx, menuStorageService)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "cmd exec error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
6
go.mod
6
go.mod
@@ -3,10 +3,10 @@ module git.grassecon.net/grassrootseconomics/sarafu-vise
|
||||
go 1.23.4
|
||||
|
||||
require (
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250103172917-3e190a44568d
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250115000535-e2d329b3f739
|
||||
git.grassecon.net/grassrootseconomics/common v0.0.0-20250113174703-6afccefd1f05
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250113213645-7c697394b5e7
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250113213325-5228aef0889b
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250115072214-bca7c5de969f
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250115003256-c0534ede1b63
|
||||
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250113103030-f0b2056fd87d
|
||||
github.com/alecthomas/assert/v2 v2.2.2
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
|
||||
12
go.sum
12
go.sum
@@ -1,11 +1,11 @@
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250103172917-3e190a44568d h1:bPAOVZOX4frSGhfOdcj7kc555f8dc9DmMd2YAyC2AMw=
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250103172917-3e190a44568d/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250115000535-e2d329b3f739 h1:w7pj1oh7jXrfajahVYU7m7AfHst4C6jNVzDVoaqJ7e8=
|
||||
git.defalsify.org/vise.git v0.2.3-0.20250115000535-e2d329b3f739/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
|
||||
git.grassecon.net/grassrootseconomics/common v0.0.0-20250113174703-6afccefd1f05 h1:BenzGx6aDHKDwE23/mWIFD2InYIXyzHroZWV3MF5WUk=
|
||||
git.grassecon.net/grassrootseconomics/common v0.0.0-20250113174703-6afccefd1f05/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250113213645-7c697394b5e7 h1:P+Bi5jcQbnCrLnKNC5k8XDTBsocyZTVifqDyZY6d0w8=
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250113213645-7c697394b5e7/go.mod h1:X9aQF93xw3vcW2QftJfzLewvbotRM0U00DRtdmFw294=
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250113213325-5228aef0889b h1:6SieNUSEKbkjzquuwazs/lVG56zdEWF10zQQEMRJfMs=
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250113213325-5228aef0889b/go.mod h1:E6W7ZOa7ZvVr0Bc5ot0LNSwpSPYq4hXlAIvEPy3AJ7U=
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250115072214-bca7c5de969f h1:FgccQi8vipX6dUt+GRiRDYHMR3UqC+plz73vw7y3fyU=
|
||||
git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250115072214-bca7c5de969f/go.mod h1:tbA4whUGMUIDgQVdIW0sxWPuuXOvZRSny5zeku5hX4k=
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250115003256-c0534ede1b63 h1:bX7klKZpX+ZZu1LKbtOXDAhV/KK0YwExehiIi0jusAM=
|
||||
git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250115003256-c0534ede1b63/go.mod h1:Syw9TZyigPAM7t9FvicOm36iUnidt45f0SxzT2JniQ8=
|
||||
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250113103030-f0b2056fd87d h1:q/NO1rEgK3pia32D/tCq5hXfEuJp84COZRwceFvy/MM=
|
||||
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250113103030-f0b2056fd87d/go.mod h1:AH15xABcvaJr1TCGlih3oGSuwWC0E5IdbHQwuu+E1KI=
|
||||
github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk=
|
||||
|
||||
@@ -18,17 +18,17 @@ import (
|
||||
"git.defalsify.org/vise.git/persist"
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.defalsify.org/vise.git/state"
|
||||
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
||||
"git.grassecon.net/grassrootseconomics/common/hex"
|
||||
"git.grassecon.net/grassrootseconomics/common/identity"
|
||||
commonlang "git.grassecon.net/grassrootseconomics/common/lang"
|
||||
"git.grassecon.net/grassrootseconomics/common/person"
|
||||
"git.grassecon.net/grassrootseconomics/common/phone"
|
||||
"git.grassecon.net/grassrootseconomics/common/pin"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/profile"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
|
||||
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
"git.grassecon.net/grassrootseconomics/common/hex"
|
||||
commonlang "git.grassecon.net/grassrootseconomics/common/lang"
|
||||
"git.grassecon.net/grassrootseconomics/common/pin"
|
||||
"git.grassecon.net/grassrootseconomics/common/person"
|
||||
"git.grassecon.net/grassrootseconomics/common/phone"
|
||||
"git.grassecon.net/grassrootseconomics/common/identity"
|
||||
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -37,9 +37,10 @@ var (
|
||||
translationDir = path.Join(scriptDir, "locale")
|
||||
)
|
||||
|
||||
// TODO: this is only in use in testing, should be moved to test domain and/or replaced by asm.FlagParser
|
||||
// FlagManager handles centralized flag management
|
||||
type FlagManager struct {
|
||||
parser *asm.FlagParser
|
||||
*asm.FlagParser
|
||||
}
|
||||
|
||||
// NewFlagManager creates a new FlagManager instance
|
||||
@@ -51,13 +52,17 @@ func NewFlagManager(csvPath string) (*FlagManager, error) {
|
||||
}
|
||||
|
||||
return &FlagManager{
|
||||
parser: parser,
|
||||
FlagParser: parser,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fm *FlagManager) SetDebug() {
|
||||
fm.FlagParser = fm.FlagParser.WithDebug()
|
||||
}
|
||||
|
||||
// GetFlag retrieves a flag value by its label
|
||||
func (fm *FlagManager) GetFlag(label string) (uint32, error) {
|
||||
return fm.parser.GetFlag(label)
|
||||
return fm.FlagParser.GetFlag(label)
|
||||
}
|
||||
|
||||
type MenuHandlers struct {
|
||||
@@ -65,8 +70,7 @@ type MenuHandlers struct {
|
||||
st *state.State
|
||||
ca cache.Memory
|
||||
userdataStore store.DataStore
|
||||
adminstore *store.AdminStore
|
||||
flagManager *asm.FlagParser
|
||||
flagManager *FlagManager
|
||||
accountService remote.AccountService
|
||||
prefixDb storedb.PrefixDb
|
||||
profile *profile.Profile
|
||||
@@ -74,7 +78,7 @@ type MenuHandlers struct {
|
||||
}
|
||||
|
||||
// NewHandlers creates a new instance of the Handlers struct with the provided dependencies.
|
||||
func NewMenuHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *store.AdminStore, accountService remote.AccountService, replaceSeparatorFunc func(string) string) (*MenuHandlers, error) {
|
||||
func NewMenuHandlers(appFlags *FlagManager, userdataStore db.Db, accountService remote.AccountService, replaceSeparatorFunc func(string) string) (*MenuHandlers, error) {
|
||||
if userdataStore == nil {
|
||||
return nil, fmt.Errorf("cannot create handler with nil userdata store")
|
||||
}
|
||||
@@ -89,7 +93,6 @@ func NewMenuHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *
|
||||
h := &MenuHandlers{
|
||||
userdataStore: userDb,
|
||||
flagManager: appFlags,
|
||||
adminstore: adminstore,
|
||||
accountService: accountService,
|
||||
prefixDb: prefixDb,
|
||||
profile: &profile.Profile{Max: 6},
|
||||
@@ -98,17 +101,14 @@ func NewMenuHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// WithPersister sets persister instance to the handlers.
|
||||
//func (h *MenuHandlers) WithPersister(pe *persist.Persister) *MenuHandlers {
|
||||
// SetPersister sets persister instance to the handlers.
|
||||
func (h *MenuHandlers) SetPersister(pe *persist.Persister) {
|
||||
if h.pe != nil {
|
||||
panic("persister already set")
|
||||
}
|
||||
h.pe = pe
|
||||
//return h
|
||||
}
|
||||
|
||||
|
||||
// Init initializes the handler for a new session.
|
||||
func (h *MenuHandlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var r resource.Result
|
||||
@@ -133,15 +133,6 @@ func (h *MenuHandlers) Init(ctx context.Context, sym string, input []byte) (reso
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
}
|
||||
|
||||
flag_admin_privilege, _ := h.flagManager.GetFlag("flag_admin_privilege")
|
||||
isAdmin, _ := h.adminstore.IsAdmin(sessionId)
|
||||
|
||||
if isAdmin {
|
||||
r.FlagSet = append(r.FlagSet, flag_admin_privilege)
|
||||
} else {
|
||||
r.FlagReset = append(r.FlagReset, flag_admin_privilege)
|
||||
}
|
||||
|
||||
if h.st == nil || h.ca == nil {
|
||||
logg.ErrorCtxf(ctx, "perister fail in handler", "state", h.st, "cache", h.ca)
|
||||
return r, fmt.Errorf("cannot get state and memory for handler")
|
||||
@@ -1076,6 +1067,8 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
|
||||
}
|
||||
|
||||
// ValidateRecipient validates that the given input is valid.
|
||||
//
|
||||
// TODO: split up functino
|
||||
func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
store := h.userdataStore
|
||||
@@ -2185,6 +2178,23 @@ func (h *MenuHandlers) resetIncorrectPINAttempts(ctx context.Context, sessionId
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MenuHandlers) persistInitialLanguageCode(ctx context.Context, sessionId string, code string) error {
|
||||
store := h.userdataStore
|
||||
_, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INITIAL_LANGUAGE_CODE)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !db.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
err = store.WriteEntry(ctx, sessionId, storedb.DATA_INITIAL_LANGUAGE_CODE, []byte(code))
|
||||
if err != nil {
|
||||
logg.ErrorCtxf(ctx, "failed to persist initial language code", "key", storedb.DATA_INITIAL_LANGUAGE_CODE, "value", code, "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// persistLanguageCode persists the selected ISO 639 language code
|
||||
func (h *MenuHandlers) persistLanguageCode(ctx context.Context, code string) error {
|
||||
store := h.userdataStore
|
||||
@@ -2197,5 +2207,5 @@ func (h *MenuHandlers) persistLanguageCode(ctx context.Context, code string) err
|
||||
logg.ErrorCtxf(ctx, "failed to persist language code", "key", storedb.DATA_SELECTED_LANGUAGE_CODE, "value", code, "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return h.persistInitialLanguageCode(ctx, sessionId, code)
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import (
|
||||
"git.defalsify.org/vise.git/persist"
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.defalsify.org/vise.git/state"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/models"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/testservice"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/mocks"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
|
||||
"git.grassecon.net/grassrootseconomics/common/pin"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/models"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/mocks"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/testservice"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
|
||||
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
@@ -84,7 +84,7 @@ func TestNewMenuHandlers(t *testing.T) {
|
||||
|
||||
// Test case for valid UserDataStore
|
||||
t.Run("Valid UserDataStore", func(t *testing.T) {
|
||||
handlers, err := NewMenuHandlers(fm.parser, store, nil, &accountService, mockReplaceSeparator)
|
||||
handlers, err := NewMenuHandlers(fm, store, &accountService, mockReplaceSeparator)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func TestNewMenuHandlers(t *testing.T) {
|
||||
|
||||
// Test case for nil UserDataStore
|
||||
t.Run("Nil UserDataStore", func(t *testing.T) {
|
||||
handlers, err := NewMenuHandlers(fm.parser, nil, nil, &accountService, mockReplaceSeparator)
|
||||
handlers, err := NewMenuHandlers(fm, nil, &accountService, mockReplaceSeparator)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error, got none")
|
||||
}
|
||||
@@ -132,16 +132,9 @@ func TestInit(t *testing.T) {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
adminstore, err := store.NewAdminStore(ctx, "admin_numbers")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
st := state.NewState(128)
|
||||
ca := cache.NewCache()
|
||||
|
||||
flag_admin_privilege, _ := fm.GetFlag("flag_admin_privilege")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func() (*MenuHandlers, context.Context)
|
||||
@@ -161,49 +154,40 @@ func TestInit(t *testing.T) {
|
||||
setup: func() (*MenuHandlers, context.Context) {
|
||||
pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca)
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
adminstore: adminstore,
|
||||
flagManager: fm,
|
||||
pe: pe,
|
||||
}
|
||||
return h, context.WithValue(ctx, "SessionId", sessionId)
|
||||
},
|
||||
input: []byte("1"),
|
||||
expectedResult: resource.Result{
|
||||
FlagReset: []uint32{flag_admin_privilege},
|
||||
},
|
||||
input: []byte("1"),
|
||||
expectedResult: resource.Result{},
|
||||
},
|
||||
{
|
||||
name: "Non-admin session initialization",
|
||||
setup: func() (*MenuHandlers, context.Context) {
|
||||
pe := persist.NewPersister(testStore).WithSession("0712345678").WithContent(st, ca)
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
adminstore: adminstore,
|
||||
flagManager: fm,
|
||||
pe: pe,
|
||||
}
|
||||
return h, context.WithValue(context.Background(), "SessionId", "0712345678")
|
||||
},
|
||||
input: []byte("1"),
|
||||
expectedResult: resource.Result{
|
||||
FlagReset: []uint32{flag_admin_privilege},
|
||||
},
|
||||
input: []byte("1"),
|
||||
expectedResult: resource.Result{},
|
||||
},
|
||||
{
|
||||
name: "Move to top node on empty input",
|
||||
setup: func() (*MenuHandlers, context.Context) {
|
||||
pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca)
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
adminstore: adminstore,
|
||||
flagManager: fm,
|
||||
pe: pe,
|
||||
}
|
||||
st.Code = []byte("some pending bytecode")
|
||||
return h, context.WithValue(ctx, "SessionId", sessionId)
|
||||
},
|
||||
input: []byte(""),
|
||||
expectedResult: resource.Result{
|
||||
FlagReset: []uint32{flag_admin_privilege},
|
||||
},
|
||||
input: []byte(""),
|
||||
expectedResult: resource.Result{},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -256,7 +240,7 @@ func TestCreateAccount(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
mockAccountService.On("CreateAccount").Return(tt.serverResponse, nil)
|
||||
@@ -281,7 +265,6 @@ func TestWithPersister(t *testing.T) {
|
||||
h.SetPersister(p)
|
||||
|
||||
assert.Equal(t, p, h.pe, "The persister should be set correctly.")
|
||||
//assert.Equal(t, h, result, "The returned handler should be the same instance.")
|
||||
}
|
||||
|
||||
func TestWithPersister_PanicWhenAlreadySet(t *testing.T) {
|
||||
@@ -320,7 +303,7 @@ func TestSaveFirstname(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock store
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -365,7 +348,7 @@ func TestSaveFamilyname(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
st: mockState,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
// Call the method
|
||||
@@ -408,7 +391,7 @@ func TestSaveYoB(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock store
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -452,7 +435,7 @@ func TestSaveLocation(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock store
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -496,7 +479,7 @@ func TestSaveOfferings(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock store
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -564,7 +547,7 @@ func TestSaveGender(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
st: mockState,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
expectedResult := resource.Result{}
|
||||
@@ -595,11 +578,11 @@ func TestSaveTemporaryPin(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin")
|
||||
flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin")
|
||||
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
userdataStore: store,
|
||||
}
|
||||
|
||||
@@ -812,7 +795,7 @@ func TestSetLanguage(t *testing.T) {
|
||||
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
userdataStore: store,
|
||||
st: mockState,
|
||||
}
|
||||
@@ -825,6 +808,17 @@ func TestSetLanguage(t *testing.T) {
|
||||
|
||||
// Assert that the Result FlagSet has the required flags after language switch
|
||||
assert.Equal(t, res, tt.expectedResult, "Result should match expected result")
|
||||
code, err := store.ReadEntry(ctx, sessionId, storedb.DATA_SELECTED_LANGUAGE_CODE)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, string(code), tt.expectedResult.Content)
|
||||
code, err = store.ReadEntry(ctx, sessionId, storedb.DATA_INITIAL_LANGUAGE_CODE)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, string(code), "eng")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -835,7 +829,7 @@ func TestResetAllowUpdate(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update")
|
||||
flag_allow_update, _ := fm.GetFlag("flag_allow_update")
|
||||
|
||||
// Define test cases
|
||||
tests := []struct {
|
||||
@@ -856,7 +850,7 @@ func TestResetAllowUpdate(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
// Call the method
|
||||
@@ -877,7 +871,7 @@ func TestResetAccountAuthorized(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag_account_authorized, _ := fm.parser.GetFlag("flag_account_authorized")
|
||||
flag_account_authorized, _ := fm.GetFlag("flag_account_authorized")
|
||||
|
||||
// Define test cases
|
||||
tests := []struct {
|
||||
@@ -898,7 +892,7 @@ func TestResetAccountAuthorized(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
// Call the method
|
||||
@@ -922,8 +916,8 @@ func TestIncorrectPinReset(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin")
|
||||
flag_account_blocked, _ := fm.parser.GetFlag("flag_account_blocked")
|
||||
flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin")
|
||||
flag_account_blocked, _ := fm.GetFlag("flag_account_blocked")
|
||||
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
|
||||
@@ -981,7 +975,7 @@ func TestIncorrectPinReset(t *testing.T) {
|
||||
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
userdataStore: store,
|
||||
}
|
||||
|
||||
@@ -1003,7 +997,7 @@ func TestResetIncorrectYob(t *testing.T) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format")
|
||||
flag_incorrect_date_format, _ := fm.GetFlag("flag_incorrect_date_format")
|
||||
|
||||
// Define test cases
|
||||
tests := []struct {
|
||||
@@ -1024,7 +1018,7 @@ func TestResetIncorrectYob(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create the MenuHandlers instance with the mock flag manager
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
// Call the method
|
||||
@@ -1062,7 +1056,7 @@ func TestAuthorize(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -1130,12 +1124,12 @@ func TestVerifyYob(t *testing.T) {
|
||||
// Create required mocks
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
mockState := state.NewState(16)
|
||||
flag_incorrect_date_format, _ := fm.parser.GetFlag("flag_incorrect_date_format")
|
||||
flag_incorrect_date_format, _ := fm.GetFlag("flag_incorrect_date_format")
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
h := &MenuHandlers{
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -1195,14 +1189,14 @@ func TestVerifyCreatePin(t *testing.T) {
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
mockState := state.NewState(16)
|
||||
|
||||
flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin")
|
||||
flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch")
|
||||
flag_pin_set, _ := fm.parser.GetFlag("flag_pin_set")
|
||||
flag_valid_pin, _ := fm.GetFlag("flag_valid_pin")
|
||||
flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch")
|
||||
flag_pin_set, _ := fm.GetFlag("flag_pin_set")
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
st: mockState,
|
||||
}
|
||||
|
||||
@@ -1296,7 +1290,7 @@ func TestCheckAccountStatus(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
err = store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey))
|
||||
@@ -1336,7 +1330,7 @@ func TestTransactionReset(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1376,14 +1370,14 @@ func TestResetTransactionAmount(t *testing.T) {
|
||||
t.Logf(err.Error())
|
||||
}
|
||||
|
||||
flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount")
|
||||
flag_invalid_amount, _ := fm.GetFlag("flag_invalid_amount")
|
||||
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -1420,14 +1414,14 @@ func TestInitiateTransaction(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Logf(err.Error())
|
||||
}
|
||||
account_authorized_flag, _ := fm.parser.GetFlag("flag_account_authorized")
|
||||
account_authorized_flag, _ := fm.GetFlag("flag_account_authorized")
|
||||
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -1513,7 +1507,7 @@ func TestQuit(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Logf(err.Error())
|
||||
}
|
||||
flag_account_authorized, _ := fm.parser.GetFlag("flag_account_authorized")
|
||||
flag_account_authorized, _ := fm.GetFlag("flag_account_authorized")
|
||||
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
|
||||
@@ -1523,7 +1517,7 @@ func TestQuit(t *testing.T) {
|
||||
|
||||
h := &MenuHandlers{
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1566,14 +1560,14 @@ func TestValidateAmount(t *testing.T) {
|
||||
ctx, store := InitializeTestStore(t)
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
|
||||
flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount")
|
||||
flag_invalid_amount, _ := fm.GetFlag("flag_invalid_amount")
|
||||
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1640,8 +1634,8 @@ func TestValidateRecipient(t *testing.T) {
|
||||
ctx, store := InitializeTestStore(t)
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
|
||||
flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient")
|
||||
flag_invalid_recipient_with_invite, _ := fm.parser.GetFlag("flag_invalid_recipient_with_invite")
|
||||
flag_invalid_recipient, _ := fm.GetFlag("flag_invalid_recipient")
|
||||
flag_invalid_recipient_with_invite, _ := fm.GetFlag("flag_invalid_recipient_with_invite")
|
||||
|
||||
// Define test cases
|
||||
tests := []struct {
|
||||
@@ -1693,12 +1687,12 @@ func TestValidateRecipient(t *testing.T) {
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
// Create the MenuHandlers instance
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
}
|
||||
|
||||
aliasResponse := &dataserviceapi.AliasAddress{
|
||||
aliasResponse := &models.AliasAddress{
|
||||
Address: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9",
|
||||
}
|
||||
|
||||
@@ -1856,10 +1850,10 @@ func TestVerifyNewPin(t *testing.T) {
|
||||
|
||||
fm, _ := NewFlagManager(flagsPath)
|
||||
|
||||
flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin")
|
||||
flag_valid_pin, _ := fm.GetFlag("flag_valid_pin")
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
h := &MenuHandlers{
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
accountService: mockAccountService,
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
@@ -1902,11 +1896,11 @@ func TestConfirmPin(t *testing.T) {
|
||||
ctx = context.WithValue(ctx, "SessionId", sessionId)
|
||||
|
||||
fm, _ := NewFlagManager(flagsPath)
|
||||
flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch")
|
||||
flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch")
|
||||
mockAccountService := new(mocks.MockAccountService)
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
accountService: mockAccountService,
|
||||
}
|
||||
|
||||
@@ -2036,7 +2030,7 @@ func TestSetDefaultVoucher(t *testing.T) {
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
accountService: mockAccountService,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
}
|
||||
|
||||
err := store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey))
|
||||
@@ -2144,7 +2138,7 @@ func TestViewVoucher(t *testing.T) {
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
prefixDb: spdb,
|
||||
}
|
||||
|
||||
@@ -2217,7 +2211,7 @@ func TestGetVoucherDetails(t *testing.T) {
|
||||
|
||||
h := &MenuHandlers{
|
||||
userdataStore: store,
|
||||
flagManager: fm.parser,
|
||||
flagManager: fm,
|
||||
accountService: mockAccountService,
|
||||
}
|
||||
err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte(tokA_AAddress))
|
||||
|
||||
@@ -27,7 +27,7 @@ func (eh *EventsUpdater) handleCustodialRegistration(ctx context.Context, ev any
|
||||
}
|
||||
|
||||
func (eu *EventsUpdater) HandleCustodialRegistration(ctx context.Context, ev *apievent.EventCustodialRegistration) error {
|
||||
pe, userStore, err := eu.getStore(ctx)
|
||||
_, userStore, err := eu.getStore(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -35,11 +35,13 @@ func (eu *EventsUpdater) HandleCustodialRegistration(ctx context.Context, ev *ap
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = pe.Load(identity.SessionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
st := pe.GetState()
|
||||
st.SetFlag(accountCreatedFlag)
|
||||
return pe.Save(identity.SessionId)
|
||||
// err = pe.Load(identity.SessionId)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// st := pe.GetState()
|
||||
// st.SetFlag(accountCreatedFlag)
|
||||
// return pe.Save(identity.SessionId)
|
||||
logg.DebugCtxf(ctx, "received custodial registration event", "identity", identity)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.defalsify.org/vise.git/asm"
|
||||
"git.defalsify.org/vise.git/db"
|
||||
"git.defalsify.org/vise.git/engine"
|
||||
"git.defalsify.org/vise.git/persist"
|
||||
@@ -12,47 +11,35 @@ import (
|
||||
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
|
||||
)
|
||||
|
||||
type HandlerService interface {
|
||||
GetHandler() (*application.MenuHandlers, error)
|
||||
}
|
||||
|
||||
func getParser(fp string, debug bool) (*asm.FlagParser, error) {
|
||||
flagParser := asm.NewFlagParser().WithDebug()
|
||||
_, err := flagParser.Load(fp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return flagParser, nil
|
||||
}
|
||||
|
||||
type LocalHandlerService struct {
|
||||
Parser *asm.FlagParser
|
||||
Parser *application.FlagManager
|
||||
DbRs *resource.DbResource
|
||||
Pe *persist.Persister
|
||||
UserdataStore *db.Db
|
||||
AdminStore *store.AdminStore
|
||||
Cfg engine.Config
|
||||
Rs resource.Resource
|
||||
}
|
||||
|
||||
func NewLocalHandlerService(ctx context.Context, fp string, debug bool, dbResource *resource.DbResource, cfg engine.Config, rs resource.Resource) (*LocalHandlerService, error) {
|
||||
parser, err := getParser(fp, debug)
|
||||
parser, err := application.NewFlagManager(fp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adminstore, err := store.NewAdminStore(ctx, "admin_numbers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if debug {
|
||||
parser.SetDebug()
|
||||
}
|
||||
|
||||
return &LocalHandlerService{
|
||||
Parser: parser,
|
||||
DbRs: dbResource,
|
||||
AdminStore: adminstore,
|
||||
Cfg: cfg,
|
||||
Rs: rs,
|
||||
Parser: parser,
|
||||
DbRs: dbResource,
|
||||
Cfg: cfg,
|
||||
Rs: rs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -69,11 +56,10 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService)
|
||||
return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator)
|
||||
}
|
||||
|
||||
appHandlers, err := application.NewMenuHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService, replaceSeparatorFunc)
|
||||
appHandlers, err := application.NewMenuHandlers(ls.Parser, *ls.UserdataStore, accountService, replaceSeparatorFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//appHandlers = appHandlers.WithPersister(ls.Pe)
|
||||
appHandlers.SetPersister(ls.Pe)
|
||||
ls.DbRs.AddLocalFunc("set_language", appHandlers.SetLanguage)
|
||||
ls.DbRs.AddLocalFunc("create_account", appHandlers.CreateAccount)
|
||||
|
||||
99
internal/cmd/cmd.go
Normal file
99
internal/cmd/cmd.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
|
||||
)
|
||||
|
||||
var (
|
||||
logg = logging.NewVanilla().WithDomain("cmd").WithContextKey("SessionId")
|
||||
)
|
||||
|
||||
type Cmd struct {
|
||||
sessionId string
|
||||
conn storage.ConnData
|
||||
flagParser *application.FlagManager
|
||||
cmd int
|
||||
enable bool
|
||||
exec func(ctx context.Context, ss storage.StorageService) error
|
||||
}
|
||||
|
||||
func NewCmd(conn storage.ConnData, sessionId string, flagParser *application.FlagManager) *Cmd {
|
||||
return &Cmd{
|
||||
conn: conn,
|
||||
sessionId: sessionId,
|
||||
flagParser: flagParser,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cmd) Exec(ctx context.Context, ss storage.StorageService) error {
|
||||
return c.exec(ctx, ss)
|
||||
}
|
||||
|
||||
func (c *Cmd) execAdmin(ctx context.Context, ss storage.StorageService) error {
|
||||
pe, err := ss.GetPersister(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = pe.Load(c.sessionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err := pe.Save(c.sessionId)
|
||||
if err != nil {
|
||||
logg.ErrorCtxf(ctx, "failed persister save: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
st := pe.GetState()
|
||||
flag, err := c.flagParser.GetFlag("flag_admin_privilege")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.enable {
|
||||
logg.InfoCtxf(ctx, "setting admin flag", "flag", flag)
|
||||
st.SetFlag(flag)
|
||||
} else {
|
||||
st.ResetFlag(flag)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cmd) parseCmdAdmin(cmd string, param string, more []string) (bool, error) {
|
||||
if cmd == "admin" {
|
||||
if param == "1" {
|
||||
c.enable = true
|
||||
} else if param != "0" {
|
||||
return false, fmt.Errorf("invalid parameter: %v", param)
|
||||
}
|
||||
c.exec = c.execAdmin
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *Cmd) Parse(args []string) error {
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("Wrong number of arguments: %v", args)
|
||||
}
|
||||
cmd := args[0]
|
||||
param := args[1]
|
||||
args = args[2:]
|
||||
|
||||
r, err := c.parseCmdAdmin(cmd, param, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown subcommand: %s", cmd)
|
||||
}
|
||||
|
||||
|
||||
50
services/local.go
Normal file
50
services/local.go
Normal file
@@ -0,0 +1,50 @@
|
||||
// +build !online
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
devremote "git.grassecon.net/grassrootseconomics/sarafu-api/dev"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/event"
|
||||
)
|
||||
|
||||
type localEmitter struct {
|
||||
h *apievent.EventsHandler
|
||||
}
|
||||
|
||||
func (d *localEmitter) emit(ctx context.Context, msg apievent.Msg) error {
|
||||
var err error
|
||||
if msg.Typ == apievent.EventTokenTransferTag {
|
||||
tx, ok := msg.Item.(devremote.Tx)
|
||||
if !ok {
|
||||
return fmt.Errorf("not a valid tx")
|
||||
}
|
||||
ev := tx.ToTransferEvent()
|
||||
err = d.h.Handle(ctx, apievent.EventTokenTransferTag, &ev)
|
||||
} else if msg.Typ == apievent.EventRegistrationTag {
|
||||
acc, ok := msg.Item.(devremote.Account)
|
||||
if !ok {
|
||||
return fmt.Errorf("not a valid tx")
|
||||
}
|
||||
ev := acc.ToRegistrationEvent()
|
||||
err = d.h.Handle(ctx, apievent.EventRegistrationTag, &ev)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func New(ctx context.Context, storageService storage.StorageService, conn storage.ConnData) remote.AccountService {
|
||||
svc := devremote.NewDevAccountService(ctx, storageService)
|
||||
svc = svc.WithAutoVoucher(ctx, "FOO", 42)
|
||||
eu := event.NewEventsUpdater(svc, storageService)
|
||||
emitter := &localEmitter{
|
||||
h: eu.ToEventsHandler(),
|
||||
}
|
||||
svc = svc.WithEmitter(emitter.emit)
|
||||
svc.AddVoucher(ctx, "BAR")
|
||||
return svc
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
Your account is still being created.
|
||||
Your account is still being created. For more help, please call: 0757628885
|
||||
@@ -1 +1 @@
|
||||
Akaunti yako bado inatengenezwa
|
||||
Akaunti yako bado inatengenezwa. Kwa usaidizi zaidi, piga: 0757628885
|
||||
@@ -3,7 +3,7 @@ CATCH select_language flag_language_set 0
|
||||
CATCH terms flag_account_created 0
|
||||
LOAD check_account_status 0
|
||||
RELOAD check_account_status
|
||||
CATCH api_failure flag_api_call_error 1
|
||||
CATCH api_failure flag_api_call_error 1
|
||||
CATCH account_pending flag_account_pending 1
|
||||
CATCH create_pin flag_pin_set 0
|
||||
CATCH main flag_account_success 1
|
||||
|
||||
15
services/remote.go
Normal file
15
services/remote.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build online
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
)
|
||||
|
||||
func New(ctx context.Context, storageService storage.StorageService, conn storage.ConnData) remote.AccountService {
|
||||
return &httpremote.HTTPAccountService{}
|
||||
}
|
||||
@@ -44,6 +44,8 @@ func(s *SshKeyStore) AddFromFile(ctx context.Context, fp string, sessionId strin
|
||||
return fmt.Errorf("Failed to parse public key: %v", err)
|
||||
}
|
||||
k := append([]byte{0x01}, pubKey.Marshal()...)
|
||||
s.store.SetLanguage(nil)
|
||||
s.store.SetSession("")
|
||||
s.store.SetPrefix(storage.DATATYPE_EXTEND)
|
||||
logg.Infof("Added key", "sessionId", sessionId, "public key", string(publicBytes))
|
||||
return s.store.Put(ctx, k, []byte(sessionId))
|
||||
@@ -51,6 +53,7 @@ func(s *SshKeyStore) AddFromFile(ctx context.Context, fp string, sessionId strin
|
||||
|
||||
func(s *SshKeyStore) Get(ctx context.Context, pubKey ssh.PublicKey) (string, error) {
|
||||
s.store.SetLanguage(nil)
|
||||
s.store.SetSession("")
|
||||
s.store.SetPrefix(storage.DATATYPE_EXTEND)
|
||||
k := append([]byte{0x01}, pubKey.Marshal()...)
|
||||
v, err := s.store.Get(ctx, k)
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.defalsify.org/vise.git/state"
|
||||
"git.grassecon.net/grassrootseconomics/visedriver/storage"
|
||||
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
|
||||
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
|
||||
)
|
||||
|
||||
@@ -180,7 +180,8 @@ func(s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) {
|
||||
}
|
||||
|
||||
// TODO: clear up why pointer here and by-value other cmds
|
||||
accountService := &httpremote.HTTPAccountService{}
|
||||
accountService := services.New(ctx, menuStorageService, s.Conn)
|
||||
|
||||
hl, err := lhs.GetHandler(accountService)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.defalsify.org/vise.git/db"
|
||||
fsdb "git.defalsify.org/vise.git/db/fs"
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
)
|
||||
|
||||
var (
|
||||
logg = logging.NewVanilla().WithDomain("adminstore")
|
||||
)
|
||||
|
||||
type AdminStore struct {
|
||||
ctx context.Context
|
||||
FsStore db.Db
|
||||
}
|
||||
|
||||
func NewAdminStore(ctx context.Context, fileName string) (*AdminStore, error) {
|
||||
fsStore, err := getFsStore(ctx, fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &AdminStore{ctx: ctx, FsStore: fsStore}, nil
|
||||
}
|
||||
|
||||
func getFsStore(ctx context.Context, connectStr string) (db.Db, error) {
|
||||
fsStore := fsdb.NewFsDb()
|
||||
err := fsStore.Connect(ctx, connectStr)
|
||||
fsStore.SetPrefix(db.DATATYPE_USERDATA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fsStore, nil
|
||||
}
|
||||
|
||||
// Checks if the given sessionId is listed as an admin.
|
||||
func (as *AdminStore) IsAdmin(sessionId string) (bool, error) {
|
||||
_, err := as.FsStore.Get(as.ctx, []byte(sessionId))
|
||||
if err != nil {
|
||||
if db.IsNotFound(err) {
|
||||
logg.Printf(logging.LVL_INFO, "Returning false because session id was not found")
|
||||
return false, nil
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -59,6 +59,8 @@ const (
|
||||
DATA_INCORRECT_PIN_ATTEMPTS
|
||||
//ISO 639 code for the selected language.
|
||||
DATA_SELECTED_LANGUAGE_CODE
|
||||
//ISO 639 code for the language initially selected.
|
||||
DATA_INITIAL_LANGUAGE_CODE
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -6,10 +6,15 @@ import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
|
||||
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
logg = logging.NewVanilla().WithDomain("vouchers").WithContextKey("SessionId")
|
||||
)
|
||||
|
||||
// VoucherMetadata helps organize data fields
|
||||
type VoucherMetadata struct {
|
||||
Symbols string
|
||||
|
||||
Reference in New Issue
Block a user