Compare commits

..

20 Commits

Author SHA1 Message Date
alfred-mk
fbfd81c94e removed the SetAccountFlags function to move it to sarafu-ussd-instance 2025-01-20 15:03:59 +03:00
alfred-mk
bad273fa58 removed leftover commented code 2025-01-20 10:56:12 +03:00
alfred-mk
ccd9e9cd77 Merge branch 'master' into data-migration 2025-01-20 10:43:17 +03:00
71ff251d51 Merge pull request 'lash/admin-tool' (#8) from lash/admin-tool into master
Reviewed-on: #8
2025-01-17 10:02:04 +01:00
alfred-mk
4cc0de59a7 updated tests 2025-01-17 11:45:55 +03:00
alfred-mk
4b8505680b added logging 2025-01-17 11:45:27 +03:00
alfred-mk
104db94826 remove unused adminstore 2025-01-17 11:44:33 +03:00
alfred-mk
ecee5b4dee remove code that reset the admin flag based on the adminstore 2025-01-17 11:35:20 +03:00
lash
879baa03fc Use FlagManager instead of asm flagparser directly 2025-01-16 13:50:18 +00:00
lash
ecac4ae009 Merge branch 'master' into lash/admin-tool 2025-01-16 11:36:57 +00:00
lash
6b404f56c9 Factor out command parse and exec logic 2025-01-16 11:34:54 +00:00
ca7dc6779a Merge pull request 'Add contact information for help on the account pending page' (#7) from contact-info-on-pending-page into master
Reviewed-on: #7
2025-01-15 20:06:27 +01:00
alfred-mk
471bbea5ca Add contact information for help on the account pending page 2025-01-15 21:57:38 +03:00
lash
78fae3526b Fix flag count, remove session prefix from auth gdbm lookup 2025-01-15 13:40:33 +00:00
alfred-mk
cf27479fcf log the correct data key 2025-01-15 16:04:49 +03:00
alfred-mk
799d1a51fa add a fallback to swa for currently unsupported languages 2025-01-15 16:01:53 +03:00
alfred-mk
1376c7b8dd use the DATA_INITIAL_LANGUAGE_CODE to check the set language 2025-01-15 15:53:26 +03:00
lash
e410158432 Add api selector for at 2025-01-15 08:06:28 +00:00
alfred-mk
b70d6b54d1 Merge branch 'master' into data-migration 2025-01-15 11:00:08 +03:00
alfred-mk
46544b723b Added SetAccountFlags to check the available data and set the required flags 2025-01-15 10:59:02 +03:00
15 changed files with 265 additions and 247 deletions

View File

@@ -22,9 +22,8 @@ import (
at "git.grassecon.net/grassrootseconomics/visedriver-africastalking/africastalking" at "git.grassecon.net/grassrootseconomics/visedriver-africastalking/africastalking"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args" "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/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
) )
var ( var (
@@ -121,7 +120,8 @@ func main() {
os.Exit(1) os.Exit(1)
} }
accountService := &httpremote.HTTPAccountService{} accountService := services.New(ctx, menuStorageService, connData)
hl, err := lhs.GetHandler(accountService) hl, err := lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "httpaccountservice: %v\n", err) fmt.Fprintf(os.Stderr, "httpaccountservice: %v\n", err)

View File

@@ -86,7 +86,7 @@ func main() {
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(16), FlagCount: uint32(128),
} }
if stateDebug { if stateDebug {
cfg.StateDebug = true cfg.StateDebug = true

View File

@@ -1,7 +0,0 @@
{
"admins": [
{
"phonenumber" : "<replace with any admin number to test with >"
}
]
}

View File

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

View File

@@ -2,16 +2,72 @@ package main
import ( import (
"context" "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() { func main() {
ctx := context.Background() config.LoadConfig()
err := commands.Seed(ctx)
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 { 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)
} }
} }

View File

@@ -18,17 +18,17 @@ import (
"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/state" "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/profile"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store" "git.grassecon.net/grassrootseconomics/sarafu-vise/store"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
"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"
) )
var ( var (
@@ -37,9 +37,10 @@ var (
translationDir = path.Join(scriptDir, "locale") 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 // FlagManager handles centralized flag management
type FlagManager struct { type FlagManager struct {
parser *asm.FlagParser *asm.FlagParser
} }
// NewFlagManager creates a new FlagManager instance // NewFlagManager creates a new FlagManager instance
@@ -51,13 +52,17 @@ func NewFlagManager(csvPath string) (*FlagManager, error) {
} }
return &FlagManager{ return &FlagManager{
parser: parser, FlagParser: parser,
}, nil }, nil
} }
func (fm *FlagManager) SetDebug() {
fm.FlagParser = fm.FlagParser.WithDebug()
}
// GetFlag retrieves a flag value by its label // GetFlag retrieves a flag value by its label
func (fm *FlagManager) GetFlag(label string) (uint32, error) { func (fm *FlagManager) GetFlag(label string) (uint32, error) {
return fm.parser.GetFlag(label) return fm.FlagParser.GetFlag(label)
} }
type MenuHandlers struct { type MenuHandlers struct {
@@ -65,8 +70,7 @@ type MenuHandlers struct {
st *state.State st *state.State
ca cache.Memory ca cache.Memory
userdataStore store.DataStore userdataStore store.DataStore
adminstore *store.AdminStore flagManager *FlagManager
flagManager *asm.FlagParser
accountService remote.AccountService accountService remote.AccountService
prefixDb storedb.PrefixDb prefixDb storedb.PrefixDb
profile *profile.Profile profile *profile.Profile
@@ -74,7 +78,7 @@ type MenuHandlers struct {
} }
// NewHandlers creates a new instance of the Handlers struct with the provided dependencies. // 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 { 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")
} }
@@ -89,7 +93,6 @@ func NewMenuHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: userDb, userdataStore: userDb,
flagManager: appFlags, flagManager: appFlags,
adminstore: adminstore,
accountService: accountService, accountService: accountService,
prefixDb: prefixDb, prefixDb: prefixDb,
profile: &profile.Profile{Max: 6}, profile: &profile.Profile{Max: 6},
@@ -98,17 +101,14 @@ func NewMenuHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *
return h, nil return h, nil
} }
// WithPersister sets persister instance to the handlers. // SetPersister sets persister instance to the handlers.
//func (h *MenuHandlers) WithPersister(pe *persist.Persister) *MenuHandlers {
func (h *MenuHandlers) SetPersister(pe *persist.Persister) { func (h *MenuHandlers) SetPersister(pe *persist.Persister) {
if h.pe != nil { if h.pe != nil {
panic("persister already set") panic("persister already set")
} }
h.pe = pe h.pe = pe
//return h
} }
// Init initializes the handler for a new session. // Init initializes the handler for a new session.
func (h *MenuHandlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var r resource.Result 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) 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 { 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")

View File

@@ -14,11 +14,11 @@ import (
"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/state" "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/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" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"github.com/alecthomas/assert/v2" "github.com/alecthomas/assert/v2"
@@ -84,7 +84,7 @@ func TestNewMenuHandlers(t *testing.T) {
// Test case for valid UserDataStore // Test case for valid UserDataStore
t.Run("Valid UserDataStore", func(t *testing.T) { 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 { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@@ -108,7 +108,7 @@ func TestNewMenuHandlers(t *testing.T) {
// Test case for nil UserDataStore // Test case for nil UserDataStore
t.Run("Nil UserDataStore", func(t *testing.T) { 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 { if err == nil {
t.Fatal("expected an error, got none") t.Fatal("expected an error, got none")
} }
@@ -132,16 +132,9 @@ func TestInit(t *testing.T) {
t.Fatal(err.Error()) t.Fatal(err.Error())
} }
adminstore, err := store.NewAdminStore(ctx, "admin_numbers")
if err != nil {
t.Fatal(err.Error())
}
st := state.NewState(128) st := state.NewState(128)
ca := cache.NewCache() ca := cache.NewCache()
flag_admin_privilege, _ := fm.GetFlag("flag_admin_privilege")
tests := []struct { tests := []struct {
name string name string
setup func() (*MenuHandlers, context.Context) setup func() (*MenuHandlers, context.Context)
@@ -161,49 +154,40 @@ func TestInit(t *testing.T) {
setup: func() (*MenuHandlers, context.Context) { setup: func() (*MenuHandlers, context.Context) {
pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca) pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca)
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
adminstore: adminstore,
pe: pe, pe: pe,
} }
return h, context.WithValue(ctx, "SessionId", sessionId) return h, context.WithValue(ctx, "SessionId", sessionId)
}, },
input: []byte("1"), input: []byte("1"),
expectedResult: resource.Result{ expectedResult: resource.Result{},
FlagReset: []uint32{flag_admin_privilege},
},
}, },
{ {
name: "Non-admin session initialization", name: "Non-admin session initialization",
setup: func() (*MenuHandlers, context.Context) { setup: func() (*MenuHandlers, context.Context) {
pe := persist.NewPersister(testStore).WithSession("0712345678").WithContent(st, ca) pe := persist.NewPersister(testStore).WithSession("0712345678").WithContent(st, ca)
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
adminstore: adminstore,
pe: pe, pe: pe,
} }
return h, context.WithValue(context.Background(), "SessionId", "0712345678") return h, context.WithValue(context.Background(), "SessionId", "0712345678")
}, },
input: []byte("1"), input: []byte("1"),
expectedResult: resource.Result{ expectedResult: resource.Result{},
FlagReset: []uint32{flag_admin_privilege},
},
}, },
{ {
name: "Move to top node on empty input", name: "Move to top node on empty input",
setup: func() (*MenuHandlers, context.Context) { setup: func() (*MenuHandlers, context.Context) {
pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca) pe := persist.NewPersister(testStore).WithSession(sessionId).WithContent(st, ca)
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
adminstore: adminstore,
pe: pe, pe: pe,
} }
st.Code = []byte("some pending bytecode") st.Code = []byte("some pending bytecode")
return h, context.WithValue(ctx, "SessionId", sessionId) return h, context.WithValue(ctx, "SessionId", sessionId)
}, },
input: []byte(""), input: []byte(""),
expectedResult: resource.Result{ expectedResult: resource.Result{},
FlagReset: []uint32{flag_admin_privilege},
},
}, },
} }
@@ -256,7 +240,7 @@ func TestCreateAccount(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
mockAccountService.On("CreateAccount").Return(tt.serverResponse, nil) mockAccountService.On("CreateAccount").Return(tt.serverResponse, nil)
@@ -281,7 +265,6 @@ func TestWithPersister(t *testing.T) {
h.SetPersister(p) h.SetPersister(p)
assert.Equal(t, p, h.pe, "The persister should be set correctly.") 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) { func TestWithPersister_PanicWhenAlreadySet(t *testing.T) {
@@ -320,7 +303,7 @@ func TestSaveFirstname(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -365,7 +348,7 @@ func TestSaveFamilyname(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
st: mockState, st: mockState,
flagManager: fm.parser, flagManager: fm,
} }
// Call the method // Call the method
@@ -408,7 +391,7 @@ func TestSaveYoB(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -452,7 +435,7 @@ func TestSaveLocation(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -496,7 +479,7 @@ func TestSaveOfferings(t *testing.T) {
// Create the MenuHandlers instance with the mock store // Create the MenuHandlers instance with the mock store
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -564,7 +547,7 @@ func TestSaveGender(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
st: mockState, st: mockState,
flagManager: fm.parser, flagManager: fm,
} }
expectedResult := resource.Result{} expectedResult := resource.Result{}
@@ -595,11 +578,11 @@ func TestSaveTemporaryPin(t *testing.T) {
log.Fatal(err) 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 // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
userdataStore: store, userdataStore: store,
} }
@@ -812,7 +795,7 @@ func TestSetLanguage(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
userdataStore: store, userdataStore: store,
st: mockState, st: mockState,
} }
@@ -846,7 +829,7 @@ func TestResetAllowUpdate(t *testing.T) {
log.Fatal(err) log.Fatal(err)
} }
flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update") flag_allow_update, _ := fm.GetFlag("flag_allow_update")
// Define test cases // Define test cases
tests := []struct { tests := []struct {
@@ -867,7 +850,7 @@ func TestResetAllowUpdate(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
} }
// Call the method // Call the method
@@ -888,7 +871,7 @@ func TestResetAccountAuthorized(t *testing.T) {
log.Fatal(err) log.Fatal(err)
} }
flag_account_authorized, _ := fm.parser.GetFlag("flag_account_authorized") flag_account_authorized, _ := fm.GetFlag("flag_account_authorized")
// Define test cases // Define test cases
tests := []struct { tests := []struct {
@@ -909,7 +892,7 @@ func TestResetAccountAuthorized(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
} }
// Call the method // Call the method
@@ -933,8 +916,8 @@ func TestIncorrectPinReset(t *testing.T) {
log.Fatal(err) log.Fatal(err)
} }
flag_incorrect_pin, _ := fm.parser.GetFlag("flag_incorrect_pin") flag_incorrect_pin, _ := fm.GetFlag("flag_incorrect_pin")
flag_account_blocked, _ := fm.parser.GetFlag("flag_account_blocked") flag_account_blocked, _ := fm.GetFlag("flag_account_blocked")
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
@@ -992,7 +975,7 @@ func TestIncorrectPinReset(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
userdataStore: store, userdataStore: store,
} }
@@ -1014,7 +997,7 @@ func TestResetIncorrectYob(t *testing.T) {
log.Fatal(err) 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 // Define test cases
tests := []struct { tests := []struct {
@@ -1035,7 +1018,7 @@ func TestResetIncorrectYob(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Create the MenuHandlers instance with the mock flag manager // Create the MenuHandlers instance with the mock flag manager
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
} }
// Call the method // Call the method
@@ -1073,7 +1056,7 @@ func TestAuthorize(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -1141,12 +1124,12 @@ func TestVerifyYob(t *testing.T) {
// Create required mocks // Create required mocks
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
mockState := state.NewState(16) 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) ctx := context.WithValue(context.Background(), "SessionId", sessionId)
h := &MenuHandlers{ h := &MenuHandlers{
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -1206,14 +1189,14 @@ func TestVerifyCreatePin(t *testing.T) {
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
mockState := state.NewState(16) mockState := state.NewState(16)
flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") flag_valid_pin, _ := fm.GetFlag("flag_valid_pin")
flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch")
flag_pin_set, _ := fm.parser.GetFlag("flag_pin_set") flag_pin_set, _ := fm.GetFlag("flag_pin_set")
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
st: mockState, st: mockState,
} }
@@ -1307,7 +1290,7 @@ func TestCheckAccountStatus(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
err = store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(tt.publicKey))
@@ -1347,7 +1330,7 @@ func TestTransactionReset(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
tests := []struct { tests := []struct {
name string name string
@@ -1387,14 +1370,14 @@ func TestResetTransactionAmount(t *testing.T) {
t.Logf(err.Error()) 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) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
tests := []struct { tests := []struct {
@@ -1431,14 +1414,14 @@ func TestInitiateTransaction(t *testing.T) {
if err != nil { if err != nil {
t.Logf(err.Error()) 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) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
tests := []struct { tests := []struct {
@@ -1524,7 +1507,7 @@ func TestQuit(t *testing.T) {
if err != nil { if err != nil {
t.Logf(err.Error()) 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) mockAccountService := new(mocks.MockAccountService)
@@ -1534,7 +1517,7 @@ func TestQuit(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
tests := []struct { tests := []struct {
name string name string
@@ -1577,14 +1560,14 @@ func TestValidateAmount(t *testing.T) {
ctx, store := InitializeTestStore(t) ctx, store := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) 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) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
tests := []struct { tests := []struct {
name string name string
@@ -1651,8 +1634,8 @@ func TestValidateRecipient(t *testing.T) {
ctx, store := InitializeTestStore(t) ctx, store := InitializeTestStore(t)
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
flag_invalid_recipient, _ := fm.parser.GetFlag("flag_invalid_recipient") flag_invalid_recipient, _ := fm.GetFlag("flag_invalid_recipient")
flag_invalid_recipient_with_invite, _ := fm.parser.GetFlag("flag_invalid_recipient_with_invite") flag_invalid_recipient_with_invite, _ := fm.GetFlag("flag_invalid_recipient_with_invite")
// Define test cases // Define test cases
tests := []struct { tests := []struct {
@@ -1704,7 +1687,7 @@ func TestValidateRecipient(t *testing.T) {
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
// Create the MenuHandlers instance // Create the MenuHandlers instance
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
} }
@@ -1867,10 +1850,10 @@ func TestVerifyNewPin(t *testing.T) {
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
flag_valid_pin, _ := fm.parser.GetFlag("flag_valid_pin") flag_valid_pin, _ := fm.GetFlag("flag_valid_pin")
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
flagManager: fm.parser, flagManager: fm,
accountService: mockAccountService, accountService: mockAccountService,
} }
ctx := context.WithValue(context.Background(), "SessionId", sessionId) ctx := context.WithValue(context.Background(), "SessionId", sessionId)
@@ -1913,11 +1896,11 @@ func TestConfirmPin(t *testing.T) {
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
fm, _ := NewFlagManager(flagsPath) fm, _ := NewFlagManager(flagsPath)
flag_pin_mismatch, _ := fm.parser.GetFlag("flag_pin_mismatch") flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch")
mockAccountService := new(mocks.MockAccountService) mockAccountService := new(mocks.MockAccountService)
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
accountService: mockAccountService, accountService: mockAccountService,
} }
@@ -2047,7 +2030,7 @@ func TestSetDefaultVoucher(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
accountService: mockAccountService, accountService: mockAccountService,
flagManager: fm.parser, flagManager: fm,
} }
err := store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) err := store.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey))
@@ -2155,7 +2138,7 @@ func TestViewVoucher(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
prefixDb: spdb, prefixDb: spdb,
} }
@@ -2228,7 +2211,7 @@ func TestGetVoucherDetails(t *testing.T) {
h := &MenuHandlers{ h := &MenuHandlers{
userdataStore: store, userdataStore: store,
flagManager: fm.parser, flagManager: fm,
accountService: mockAccountService, accountService: mockAccountService,
} }
err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte(tokA_AAddress)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte(tokA_AAddress))

View File

@@ -4,7 +4,6 @@ import (
"context" "context"
"strings" "strings"
"git.defalsify.org/vise.git/asm"
"git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/db"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/persist"
@@ -12,47 +11,35 @@ import (
"git.grassecon.net/grassrootseconomics/sarafu-api/remote" "git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
) )
type HandlerService interface { type HandlerService interface {
GetHandler() (*application.MenuHandlers, error) 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 { type LocalHandlerService struct {
Parser *asm.FlagParser Parser *application.FlagManager
DbRs *resource.DbResource DbRs *resource.DbResource
Pe *persist.Persister Pe *persist.Persister
UserdataStore *db.Db UserdataStore *db.Db
AdminStore *store.AdminStore
Cfg engine.Config Cfg engine.Config
Rs resource.Resource Rs resource.Resource
} }
func NewLocalHandlerService(ctx context.Context, fp string, debug bool, dbResource *resource.DbResource, cfg engine.Config, rs resource.Resource) (*LocalHandlerService, error) { 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 { if err != nil {
return nil, err return nil, err
} }
adminstore, err := store.NewAdminStore(ctx, "admin_numbers") if debug {
if err != nil { parser.SetDebug()
return nil, err
} }
return &LocalHandlerService{ return &LocalHandlerService{
Parser: parser, Parser: parser,
DbRs: dbResource, DbRs: dbResource,
AdminStore: adminstore, Cfg: cfg,
Cfg: cfg, Rs: rs,
Rs: rs,
}, nil }, nil
} }
@@ -69,11 +56,10 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService)
return strings.ReplaceAll(input, ":", ls.Cfg.MenuSeparator) 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 { if err != nil {
return nil, err return nil, err
} }
//appHandlers = appHandlers.WithPersister(ls.Pe)
appHandlers.SetPersister(ls.Pe) appHandlers.SetPersister(ls.Pe)
ls.DbRs.AddLocalFunc("set_language", appHandlers.SetLanguage) ls.DbRs.AddLocalFunc("set_language", appHandlers.SetLanguage)
ls.DbRs.AddLocalFunc("create_account", appHandlers.CreateAccount) ls.DbRs.AddLocalFunc("create_account", appHandlers.CreateAccount)

99
internal/cmd/cmd.go Normal file
View 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)
}

View File

@@ -1 +1 @@
Your account is still being created. Your account is still being created. For more help, please call: 0757628885

View File

@@ -1 +1 @@
Akaunti yako bado inatengenezwa Akaunti yako bado inatengenezwa. Kwa usaidizi zaidi, piga: 0757628885

View File

@@ -3,7 +3,7 @@ CATCH select_language flag_language_set 0
CATCH terms flag_account_created 0 CATCH terms flag_account_created 0
LOAD check_account_status 0 LOAD check_account_status 0
RELOAD check_account_status 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 account_pending flag_account_pending 1
CATCH create_pin flag_pin_set 0 CATCH create_pin flag_pin_set 0
CATCH main flag_account_success 1 CATCH main flag_account_success 1

View File

@@ -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) return fmt.Errorf("Failed to parse public key: %v", err)
} }
k := append([]byte{0x01}, pubKey.Marshal()...) k := append([]byte{0x01}, pubKey.Marshal()...)
s.store.SetLanguage(nil)
s.store.SetSession("")
s.store.SetPrefix(storage.DATATYPE_EXTEND) s.store.SetPrefix(storage.DATATYPE_EXTEND)
logg.Infof("Added key", "sessionId", sessionId, "public key", string(publicBytes)) logg.Infof("Added key", "sessionId", sessionId, "public key", string(publicBytes))
return s.store.Put(ctx, k, []byte(sessionId)) 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) { func(s *SshKeyStore) Get(ctx context.Context, pubKey ssh.PublicKey) (string, error) {
s.store.SetLanguage(nil) s.store.SetLanguage(nil)
s.store.SetSession("")
s.store.SetPrefix(storage.DATATYPE_EXTEND) s.store.SetPrefix(storage.DATATYPE_EXTEND)
k := append([]byte{0x01}, pubKey.Marshal()...) k := append([]byte{0x01}, pubKey.Marshal()...)
v, err := s.store.Get(ctx, k) v, err := s.store.Get(ctx, k)

View File

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

View File

@@ -6,10 +6,15 @@ import (
"math/big" "math/big"
"strings" "strings"
"git.defalsify.org/vise.git/logging"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api"
) )
var (
logg = logging.NewVanilla().WithDomain("vouchers").WithContextKey("SessionId")
)
// VoucherMetadata helps organize data fields // VoucherMetadata helps organize data fields
type VoucherMetadata struct { type VoucherMetadata struct {
Symbols string Symbols string