Compare commits
68 Commits
profile-up
...
pin-reset
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dbe74d12b
|
||
|
|
332074375a
|
||
|
|
5e4a9e7567
|
||
|
|
eb2c73dce1
|
||
|
|
7e448f739a
|
||
|
|
0014693ba8
|
||
| 45945ae9c5 | |||
|
|
d7ea8fa651
|
||
|
|
e75aa2c1f7 | ||
|
|
63eed81d3d
|
||
|
|
f4ca4454ea
|
||
|
|
2704069e74
|
||
|
|
7d1a04f089
|
||
|
|
53fa6f64ce
|
||
|
|
7fa38340dd
|
||
|
|
7aab3cff8c
|
||
|
|
299534ccf1
|
||
|
|
b2655b7f11
|
||
|
|
5abe9b78cc
|
||
|
|
12825ae08a
|
||
|
|
ac0b4b2ed1
|
||
| 5f666382ab | |||
|
|
8fe8ff540b
|
||
|
|
0b4bf58107
|
||
|
|
767a3cd64c
|
||
|
|
c4078c5280
|
||
|
|
d434194021
|
||
|
|
c6ca3f6be4
|
||
|
|
8093eae61a
|
||
|
|
833d52a558
|
||
|
|
8262e14198
|
||
|
|
ea4c6d9314
|
||
|
|
7c823e07ca
|
||
|
|
41585f831c
|
||
|
|
d93a26f9b0
|
||
|
|
cf523e30f8
|
||
|
|
888d3befe9
|
||
|
|
017691a40c
|
||
|
|
dc418771a7
|
||
|
|
c2068db050
|
||
|
|
c42b1cd66b
|
||
|
|
b404ae95fb
|
||
|
|
0a97f610a4
|
||
|
|
5a0563df94
|
||
|
|
7597b96dae
|
||
|
|
f37483e2f0
|
||
|
|
d0ad6395b5
|
||
|
|
106983a394
|
||
|
|
91b85af11a
|
||
|
|
534d756318
|
||
|
|
6998c30dd1
|
||
|
|
449f90c95b
|
||
|
|
e96c874300
|
||
|
|
b35460d3c1
|
||
|
|
124049c924
|
||
|
|
5fd3eb3c29
|
||
|
|
d83962c0ba
|
||
|
|
41da099933
|
||
|
|
c9bb93ede6
|
||
|
|
ca13d9155c
|
||
|
|
e338ce0025
|
||
|
|
b97965193b
|
||
|
|
aec0abb2b6
|
||
|
|
26073c8000
|
||
|
|
e4c2f644f3
|
||
|
|
3de46cef5e
|
||
|
|
0cc0bdf9f7
|
||
|
|
72d5c186dd
|
@@ -16,3 +16,7 @@ CREATE_ACCOUNT_URL=http://localhost:5003/api/v2/account/create
|
||||
TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/
|
||||
BALANCE_URL=https://custodial.sarafu.africa/api/account/status/
|
||||
TRACK_URL=http://localhost:5003/api/v2/account/status
|
||||
|
||||
|
||||
#numbers with privileges to reset others pin
|
||||
ADMIN_NUMBERS=254051722XXX,255012221XXX
|
||||
@@ -131,7 +131,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs)
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userdataStore)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -104,8 +104,9 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs)
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userdataStore)
|
||||
|
||||
accountService := server.AccountService{}
|
||||
|
||||
hl, err := lhs.GetHandler(&accountService)
|
||||
|
||||
@@ -92,13 +92,14 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs)
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userdataStore)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
accountService := server.AccountService{}
|
||||
hl, err := lhs.GetHandler(&accountService)
|
||||
if err != nil {
|
||||
|
||||
@@ -88,7 +88,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs)
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userdatastore)
|
||||
lhs.SetPersister(pe)
|
||||
|
||||
|
||||
7
devtools/admin/admin_numbers.json
Normal file
7
devtools/admin/admin_numbers.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"admins": [
|
||||
{
|
||||
"phonenumber" : "<replace with any admin number to test with >"
|
||||
}
|
||||
]
|
||||
}
|
||||
47
devtools/admin/commands/seed.go
Normal file
47
devtools/admin/commands/seed.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"git.defalsify.org/vise.git/logging"
|
||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||
)
|
||||
|
||||
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 := utils.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
|
||||
}
|
||||
17
devtools/admin/main.go
Normal file
17
devtools/admin/main.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"git.grassecon.net/urdt/ussd/devtools/admin/commands"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
err := commands.Seed(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize a list of admins with error %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.defalsify.org/vise.git/asm"
|
||||
"git.defalsify.org/vise.git/db"
|
||||
"git.defalsify.org/vise.git/engine"
|
||||
@@ -8,6 +10,7 @@ import (
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.grassecon.net/urdt/ussd/internal/handlers/server"
|
||||
"git.grassecon.net/urdt/ussd/internal/handlers/ussd"
|
||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||
)
|
||||
|
||||
type HandlerService interface {
|
||||
@@ -28,20 +31,26 @@ type LocalHandlerService struct {
|
||||
DbRs *resource.DbResource
|
||||
Pe *persist.Persister
|
||||
UserdataStore *db.Db
|
||||
AdminStore *utils.AdminStore
|
||||
Cfg engine.Config
|
||||
Rs resource.Resource
|
||||
}
|
||||
|
||||
func NewLocalHandlerService(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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
adminstore, err := utils.NewAdminStore(ctx, "admin_numbers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &LocalHandlerService{
|
||||
Parser: parser,
|
||||
DbRs: dbResource,
|
||||
Cfg: cfg,
|
||||
Rs: rs,
|
||||
Parser: parser,
|
||||
DbRs: dbResource,
|
||||
AdminStore: adminstore,
|
||||
Cfg: cfg,
|
||||
Rs: rs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -54,7 +63,7 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) {
|
||||
}
|
||||
|
||||
func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) {
|
||||
ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore,accountService)
|
||||
ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore, ls.AdminStore, accountService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,6 +107,13 @@ func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceIn
|
||||
ls.DbRs.AddLocalFunc("get_vouchers", ussdHandlers.GetVoucherList)
|
||||
ls.DbRs.AddLocalFunc("view_voucher", ussdHandlers.ViewVoucher)
|
||||
ls.DbRs.AddLocalFunc("set_voucher", ussdHandlers.SetVoucher)
|
||||
ls.DbRs.AddLocalFunc("reset_valid_pin", ussdHandlers.ResetValidPin)
|
||||
ls.DbRs.AddLocalFunc("check_pin_mismatch", ussdHandlers.CheckPinMisMatch)
|
||||
ls.DbRs.AddLocalFunc("validate_blocked_number", ussdHandlers.ValidateBlockedNumber)
|
||||
ls.DbRs.AddLocalFunc("retrieve_blocked_number", ussdHandlers.RetrieveBlockedNumber)
|
||||
ls.DbRs.AddLocalFunc("reset_unregistered_number", ussdHandlers.ResetUnregisteredNumber)
|
||||
ls.DbRs.AddLocalFunc("reset_others_pin", ussdHandlers.ResetOthersPin)
|
||||
ls.DbRs.AddLocalFunc("save_others_temporary_pin", ussdHandlers.SaveOthersTemporaryPin)
|
||||
|
||||
return ussdHandlers, nil
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ var (
|
||||
errResponse *api.ErrResponse
|
||||
)
|
||||
|
||||
// Define the regex patterns as constants
|
||||
const (
|
||||
phoneRegex = `(\(\d{3}\)\s?|\d{3}[-.\s]?)?\d{3}[-.\s]?\d{4}`
|
||||
pinPattern = `^\d{4}$`
|
||||
)
|
||||
|
||||
// FlagManager handles centralized flag management
|
||||
type FlagManager struct {
|
||||
parser *asm.FlagParser
|
||||
@@ -63,12 +69,13 @@ type Handlers struct {
|
||||
st *state.State
|
||||
ca cache.Memory
|
||||
userdataStore utils.DataStore
|
||||
adminstore *utils.AdminStore
|
||||
flagManager *asm.FlagParser
|
||||
accountService server.AccountServiceInterface
|
||||
prefixDb storage.PrefixDb
|
||||
}
|
||||
|
||||
func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService server.AccountServiceInterface) (*Handlers, error) {
|
||||
func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, adminstore *utils.AdminStore, accountService server.AccountServiceInterface) (*Handlers, error) {
|
||||
if userdataStore == nil {
|
||||
return nil, fmt.Errorf("cannot create handler with nil userdata store")
|
||||
}
|
||||
@@ -81,21 +88,24 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService s
|
||||
h := &Handlers{
|
||||
userdataStore: userDb,
|
||||
flagManager: appFlags,
|
||||
adminstore: adminstore,
|
||||
accountService: accountService,
|
||||
prefixDb: prefixDb,
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Define the regex pattern as a constant
|
||||
const pinPattern = `^\d{4}$`
|
||||
|
||||
// isValidPIN checks whether the given input is a 4 digit number
|
||||
func isValidPIN(pin string) bool {
|
||||
match, _ := regexp.MatchString(pinPattern, pin)
|
||||
return match
|
||||
}
|
||||
|
||||
func isValidPhoneNumber(phonenumber string) bool {
|
||||
match, _ := regexp.MatchString(phoneRegex, phonenumber)
|
||||
return match
|
||||
}
|
||||
|
||||
func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers {
|
||||
if h.pe != nil {
|
||||
panic("persister already set")
|
||||
@@ -106,13 +116,25 @@ func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers {
|
||||
|
||||
func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var r resource.Result
|
||||
|
||||
if h.pe == nil {
|
||||
logg.WarnCtxf(ctx, "handler init called before it is ready or more than once", "state", h.st, "cache", h.ca)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
h.st = h.pe.GetState()
|
||||
h.ca = h.pe.GetMemory()
|
||||
|
||||
sessionId, _ := ctx.Value("SessionId").(string)
|
||||
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")
|
||||
@@ -203,6 +225,30 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) CheckPinMisMatch(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch")
|
||||
sessionId, ok := ctx.Value("SessionId").(string)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
store := h.userdataStore
|
||||
blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
temporaryPin, err := store.ReadEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if bytes.Equal(temporaryPin, input) {
|
||||
res.FlagReset = append(res.FlagReset, flag_pin_mismatch)
|
||||
} else {
|
||||
res.FlagSet = append(res.FlagSet, flag_pin_mismatch)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
res := resource.Result{}
|
||||
_, ok := ctx.Value("SessionId").(string)
|
||||
@@ -221,7 +267,7 @@ func (h *Handlers) VerifyNewPin(ctx context.Context, sym string, input []byte) (
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_PIN
|
||||
// SaveTemporaryPin saves the valid PIN input to the DATA_TEMPORARY_VALUE
|
||||
// during the account creation process
|
||||
// and during the change PIN process
|
||||
func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
@@ -234,7 +280,6 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt
|
||||
}
|
||||
|
||||
flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin")
|
||||
|
||||
accountPIN := string(input)
|
||||
|
||||
// Validate that the PIN is a 4-digit number
|
||||
@@ -242,11 +287,32 @@ func (h *Handlers) SaveTemporaryPin(ctx context.Context, sym string, input []byt
|
||||
res.FlagSet = append(res.FlagSet, flag_incorrect_pin)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.FlagReset = append(res.FlagReset, flag_incorrect_pin)
|
||||
store := h.userdataStore
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(accountPIN))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) SaveOthersTemporaryPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
var err error
|
||||
|
||||
store := h.userdataStore
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(accountPIN))
|
||||
sessionId, ok := ctx.Value("SessionId").(string)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
temporaryPin := string(input)
|
||||
blockedNumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER)
|
||||
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
err = store.WriteEntry(ctx, string(blockedNumber), utils.DATA_TEMPORARY_VALUE, []byte(temporaryPin))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -263,7 +329,7 @@ func (h *Handlers) ConfirmPinChange(ctx context.Context, sym string, input []byt
|
||||
flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch")
|
||||
|
||||
store := h.userdataStore
|
||||
temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN)
|
||||
temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -294,11 +360,10 @@ func (h *Handlers) VerifyCreatePin(ctx context.Context, sym string, input []byte
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
store := h.userdataStore
|
||||
temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_PIN)
|
||||
temporaryPin, err := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if bytes.Equal(input, temporaryPin) {
|
||||
res.FlagSet = []uint32{flag_valid_pin}
|
||||
res.FlagReset = []uint32{flag_pin_mismatch}
|
||||
@@ -338,13 +403,13 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte)
|
||||
flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update")
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
if allowUpdate {
|
||||
temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME)
|
||||
temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(temporaryFirstName))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -368,13 +433,13 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte)
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
|
||||
if allowUpdate {
|
||||
temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME)
|
||||
temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(temporaryFamilyName))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -396,13 +461,13 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
|
||||
if allowUpdate {
|
||||
temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB)
|
||||
temporaryYob, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_YOB, []byte(temporaryYob))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -426,13 +491,13 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) (
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
|
||||
if allowUpdate {
|
||||
temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION)
|
||||
temporaryLocation, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(temporaryLocation))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(location))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(location))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -456,13 +521,13 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
|
||||
if allowUpdate {
|
||||
temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER)
|
||||
temporaryGender, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(temporaryGender))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(gender))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(gender))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -486,13 +551,13 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte)
|
||||
allowUpdate := h.st.MatchFlag(flag_allow_update, true)
|
||||
|
||||
if allowUpdate {
|
||||
temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS)
|
||||
temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE)
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_OFFERINGS, []byte(temporaryOfferings))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
} else {
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings))
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings))
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
@@ -511,6 +576,14 @@ func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byt
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ResetAllowUpdate resets the allowupdate flag that allows a user to update profile data.
|
||||
func (h *Handlers) ResetValidPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin")
|
||||
res.FlagReset = append(res.FlagReset, flag_valid_pin)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ResetAccountAuthorized resets the account authorization flag after a successful PIN entry.
|
||||
func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
@@ -594,11 +667,13 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
|
||||
store := h.userdataStore
|
||||
publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey))
|
||||
if err != nil {
|
||||
res.FlagSet = append(res.FlagSet, flag_api_error)
|
||||
@@ -655,7 +730,6 @@ func (h *Handlers) VerifyYob(ctx context.Context, sym string, input []byte) (res
|
||||
var err error
|
||||
|
||||
flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format")
|
||||
|
||||
date := string(input)
|
||||
_, err = strconv.Atoi(date)
|
||||
if err != nil {
|
||||
@@ -678,7 +752,6 @@ func (h *Handlers) ResetIncorrectYob(ctx context.Context, sym string, input []by
|
||||
var res resource.Result
|
||||
|
||||
flag_incorrect_date_format, _ := h.flagManager.GetFlag("flag_incorrect_date_format")
|
||||
|
||||
res.FlagReset = append(res.FlagReset, flag_incorrect_date_format)
|
||||
return res, nil
|
||||
}
|
||||
@@ -761,6 +834,67 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetOthersPin(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
store := h.userdataStore
|
||||
sessionId, ok := ctx.Value("SessionId").(string)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
blockedPhonenumber, err := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
temporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), utils.DATA_TEMPORARY_VALUE)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
err = store.WriteEntry(ctx, string(blockedPhonenumber), utils.DATA_ACCOUNT_PIN, []byte(temporaryPin))
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ResetUnregisteredNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number")
|
||||
res.FlagReset = append(res.FlagReset, flag_unregistered_number)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *Handlers) ValidateBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
var err error
|
||||
|
||||
flag_unregistered_number, _ := h.flagManager.GetFlag("flag_unregistered_number")
|
||||
store := h.userdataStore
|
||||
sessionId, ok := ctx.Value("SessionId").(string)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
blockedNumber := string(input)
|
||||
_, err = store.ReadEntry(ctx, blockedNumber, utils.DATA_PUBLIC_KEY)
|
||||
if !isValidPhoneNumber(blockedNumber) {
|
||||
res.FlagSet = append(res.FlagSet, flag_unregistered_number)
|
||||
return res, nil
|
||||
}
|
||||
if err != nil {
|
||||
if db.IsNotFound(err) {
|
||||
logg.Printf(logging.LVL_INFO, "Invalid or unregistered number")
|
||||
res.FlagSet = append(res.FlagSet, flag_unregistered_number)
|
||||
return res, nil
|
||||
} else {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
err = store.WriteEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER, []byte(blockedNumber))
|
||||
if err != nil {
|
||||
return res, nil
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ValidateRecipient validates that the given input is a valid phone number.
|
||||
func (h *Handlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
@@ -932,6 +1066,22 @@ func (h *Handlers) GetRecipient(ctx context.Context, sym string, input []byte) (
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// RetrieveBlockedNumber gets the current number during the pin reset for other's is in progress.
|
||||
func (h *Handlers) RetrieveBlockedNumber(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
|
||||
sessionId, ok := ctx.Value("SessionId").(string)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("missing session")
|
||||
}
|
||||
store := h.userdataStore
|
||||
blockedNumber, _ := store.ReadEntry(ctx, sessionId, utils.DATA_BLOCKED_NUMBER)
|
||||
|
||||
res.Content = string(blockedNumber)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetSender returns the sessionId (phoneNumber)
|
||||
func (h *Handlers) GetSender(ctx context.Context, sym string, input []byte) (resource.Result, error) {
|
||||
var res resource.Result
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestNewHandlers(t *testing.T) {
|
||||
}
|
||||
t.Run("Valid UserDataStore", func(t *testing.T) {
|
||||
mockStore := &mocks.MockUserDataStore{}
|
||||
handlers, err := NewHandlers(fm.parser, mockStore, &accountService)
|
||||
handlers, err := NewHandlers(fm.parser, mockStore, nil, &accountService)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func TestNewHandlers(t *testing.T) {
|
||||
t.Run("Nil UserDataStore", func(t *testing.T) {
|
||||
appFlags := &asm.FlagParser{}
|
||||
|
||||
handlers, err := NewHandlers(appFlags, nil, &accountService)
|
||||
handlers, err := NewHandlers(appFlags, nil, nil, &accountService)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("expected an error, got none")
|
||||
@@ -186,7 +186,7 @@ func TestSaveFirstname(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FIRST_NAME, []byte(firstName)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(firstName)).Return(nil)
|
||||
|
||||
// Create the Handlers instance with the mock store
|
||||
h := &Handlers{
|
||||
@@ -219,7 +219,7 @@ func TestSaveFamilyname(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_FAMILY_NAME, []byte(familyName)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(familyName)).Return(nil)
|
||||
|
||||
// Create the Handlers instance with the mock store
|
||||
h := &Handlers{
|
||||
@@ -281,7 +281,7 @@ func TestSaveTemporaryPin(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN, []byte(tt.input)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.input)).Return(nil)
|
||||
|
||||
// Call the method
|
||||
res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input)
|
||||
@@ -310,7 +310,7 @@ func TestSaveYoB(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_YOB, []byte(yob)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil)
|
||||
|
||||
// Create the Handlers instance with the mock store
|
||||
h := &Handlers{
|
||||
@@ -343,7 +343,7 @@ func TestSaveLocation(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_LOCATION, []byte(yob)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(yob)).Return(nil)
|
||||
|
||||
// Create the Handlers instance with the mock store
|
||||
h := &Handlers{
|
||||
@@ -376,7 +376,7 @@ func TestSaveOfferings(t *testing.T) {
|
||||
ctx := context.WithValue(context.Background(), "SessionId", sessionId)
|
||||
|
||||
// Set up the expected behavior of the mock
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_OFFERINGS, []byte(offerings)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(offerings)).Return(nil)
|
||||
|
||||
// Create the Handlers instance with the mock store
|
||||
h := &Handlers{
|
||||
@@ -442,10 +442,10 @@ func TestSaveGender(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set up expectations for the mock database
|
||||
if tt.expectCall {
|
||||
expectedKey := utils.DATA_TEMPORARY_GENDER
|
||||
expectedKey := utils.DATA_TEMPORARY_VALUE
|
||||
mockStore.On("WriteEntry", ctx, sessionId, expectedKey, []byte(tt.expectedGender)).Return(nil)
|
||||
} else {
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender)).Return(nil)
|
||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender)).Return(nil)
|
||||
}
|
||||
mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol)
|
||||
// Create the Handlers instance with the mock store
|
||||
@@ -463,9 +463,9 @@ func TestSaveGender(t *testing.T) {
|
||||
|
||||
// Verify expectations
|
||||
if tt.expectCall {
|
||||
mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender))
|
||||
mockStore.AssertCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender))
|
||||
} else {
|
||||
mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_GENDER, []byte(tt.expectedGender))
|
||||
mockStore.AssertNotCalled(t, "WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(tt.expectedGender))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1041,7 +1041,7 @@ func TestVerifyCreatePin(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
typ := utils.DATA_TEMPORARY_PIN
|
||||
typ := utils.DATA_TEMPORARY_VALUE
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -1834,7 +1834,7 @@ func TestConfirmPin(t *testing.T) {
|
||||
// Set up the expected behavior of the mock
|
||||
mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_PIN, []byte(tt.temporarypin)).Return(nil)
|
||||
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_PIN).Return(tt.temporarypin, nil)
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return(tt.temporarypin, nil)
|
||||
|
||||
//Call the function under test
|
||||
res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.temporarypin)
|
||||
@@ -2106,16 +2106,9 @@ func TestViewVoucher(t *testing.T) {
|
||||
}
|
||||
|
||||
// Set up expectations for mockDataStore
|
||||
expectedData := map[utils.DataTyp]string{
|
||||
utils.DATA_TEMPORARY_SYM: "SRF",
|
||||
utils.DATA_TEMPORARY_BAL: "100",
|
||||
utils.DATA_TEMPORARY_DECIMAL: "6",
|
||||
utils.DATA_TEMPORARY_ADDRESS: "0xd4c288865Ce",
|
||||
}
|
||||
expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "100", "6", "0xd4c288865Ce")
|
||||
|
||||
for dataType, dataValue := range expectedData {
|
||||
mockDataStore.On("WriteEntry", ctx, sessionId, dataType, []byte(dataValue)).Return(nil)
|
||||
}
|
||||
mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE, []byte(expectedData)).Return(nil)
|
||||
|
||||
res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1"))
|
||||
assert.NoError(t, err)
|
||||
@@ -2139,6 +2132,8 @@ func TestSetVoucher(t *testing.T) {
|
||||
ContractAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9",
|
||||
}
|
||||
|
||||
expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9")
|
||||
|
||||
// Define the expected active entries
|
||||
activeEntries := map[utils.DataTyp][]byte{
|
||||
utils.DATA_ACTIVE_SYM: []byte(tempData.TokenSymbol),
|
||||
@@ -2147,30 +2142,14 @@ func TestSetVoucher(t *testing.T) {
|
||||
utils.DATA_ACTIVE_ADDRESS: []byte(tempData.ContractAddress),
|
||||
}
|
||||
|
||||
// Define the temporary entries to be cleared
|
||||
tempEntries := map[utils.DataTyp][]byte{
|
||||
utils.DATA_TEMPORARY_SYM: []byte(""),
|
||||
utils.DATA_TEMPORARY_BAL: []byte(""),
|
||||
utils.DATA_TEMPORARY_DECIMAL: []byte(""),
|
||||
utils.DATA_TEMPORARY_ADDRESS: []byte(""),
|
||||
}
|
||||
|
||||
// Mocking ReadEntry calls for temporary data retrieval
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_SYM).Return([]byte(tempData.TokenSymbol), nil)
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_BAL).Return([]byte(tempData.Balance), nil)
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_DECIMAL).Return([]byte(tempData.TokenDecimals), nil)
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_ADDRESS).Return([]byte(tempData.ContractAddress), nil)
|
||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TEMPORARY_VALUE).Return([]byte(expectedData), nil)
|
||||
|
||||
// Mocking WriteEntry calls for setting active data
|
||||
for key, value := range activeEntries {
|
||||
mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil)
|
||||
}
|
||||
|
||||
// Mocking WriteEntry calls for clearing temporary data
|
||||
for key, value := range tempEntries {
|
||||
mockDataStore.On("WriteEntry", ctx, sessionId, key, value).Return(nil)
|
||||
}
|
||||
|
||||
h := &Handlers{
|
||||
userdataStore: mockDataStore,
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs)
|
||||
lhs, err := handlers.NewLocalHandlerService(ctx, pfp, true, dbResource, cfg, rs)
|
||||
lhs.SetDataStore(&userDataStore)
|
||||
lhs.SetPersister(pe)
|
||||
|
||||
|
||||
51
internal/utils/adminstore.go
Normal file
51
internal/utils/adminstore.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package utils
|
||||
|
||||
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
|
||||
}
|
||||
@@ -14,30 +14,21 @@ const (
|
||||
DATA_CUSTODIAL_ID
|
||||
DATA_ACCOUNT_PIN
|
||||
DATA_ACCOUNT_STATUS
|
||||
DATA_TEMPORARY_FIRST_NAME
|
||||
DATA_FIRST_NAME
|
||||
DATA_TEMPORARY_FAMILY_NAME
|
||||
DATA_FAMILY_NAME
|
||||
DATA_TEMPORARY_YOB
|
||||
DATA_YOB
|
||||
DATA_TEMPORARY_LOCATION
|
||||
DATA_LOCATION
|
||||
DATA_TEMPORARY_GENDER
|
||||
DATA_GENDER
|
||||
DATA_TEMPORARY_OFFERINGS
|
||||
DATA_OFFERINGS
|
||||
DATA_RECIPIENT
|
||||
DATA_AMOUNT
|
||||
DATA_TEMPORARY_PIN
|
||||
DATA_TEMPORARY_VALUE
|
||||
DATA_VOUCHER_LIST
|
||||
DATA_TEMPORARY_SYM
|
||||
DATA_ACTIVE_SYM
|
||||
DATA_TEMPORARY_BAL
|
||||
DATA_ACTIVE_BAL
|
||||
DATA_BLOCKED_NUMBER
|
||||
DATA_PUBLIC_KEY_REVERSE
|
||||
DATA_TEMPORARY_DECIMAL
|
||||
DATA_ACTIVE_DECIMAL
|
||||
DATA_TEMPORARY_ADDRESS
|
||||
DATA_ACTIVE_ADDRESS
|
||||
|
||||
)
|
||||
|
||||
@@ -77,7 +77,7 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol,
|
||||
|
||||
for i, sym := range symList {
|
||||
parts := strings.SplitN(sym, ":", 2)
|
||||
|
||||
|
||||
if input == parts[0] || strings.EqualFold(input, parts[1]) {
|
||||
symbol = parts[1]
|
||||
if i < len(balList) {
|
||||
@@ -97,45 +97,30 @@ func MatchVoucher(input, symbols, balances, decimals, addresses string) (symbol,
|
||||
|
||||
// StoreTemporaryVoucher saves voucher metadata as temporary entries in the DataStore.
|
||||
func StoreTemporaryVoucher(ctx context.Context, store DataStore, sessionId string, data *dataserviceapi.TokenHoldings) error {
|
||||
entries := map[DataTyp][]byte{
|
||||
DATA_TEMPORARY_SYM: []byte(data.TokenSymbol),
|
||||
DATA_TEMPORARY_BAL: []byte(data.Balance),
|
||||
DATA_TEMPORARY_DECIMAL: []byte(data.TokenDecimals),
|
||||
DATA_TEMPORARY_ADDRESS: []byte(data.ContractAddress),
|
||||
tempData := fmt.Sprintf("%s,%s,%s,%s", data.TokenSymbol, data.Balance, data.TokenDecimals, data.ContractAddress)
|
||||
|
||||
if err := store.WriteEntry(ctx, sessionId, DATA_TEMPORARY_VALUE, []byte(tempData)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, value := range entries {
|
||||
if err := store.WriteEntry(ctx, sessionId, key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTemporaryVoucherData retrieves temporary voucher metadata from the DataStore.
|
||||
func GetTemporaryVoucherData(ctx context.Context, store DataStore, sessionId string) (*dataserviceapi.TokenHoldings, error) {
|
||||
keys := []DataTyp{
|
||||
DATA_TEMPORARY_SYM,
|
||||
DATA_TEMPORARY_BAL,
|
||||
DATA_TEMPORARY_DECIMAL,
|
||||
DATA_TEMPORARY_ADDRESS,
|
||||
temp_data, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
values := strings.SplitN(string(temp_data), ",", 4)
|
||||
|
||||
data := &dataserviceapi.TokenHoldings{}
|
||||
values := make([][]byte, len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
value, err := store.ReadEntry(ctx, sessionId, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values[i] = value
|
||||
}
|
||||
|
||||
data.TokenSymbol = string(values[0])
|
||||
data.Balance = string(values[1])
|
||||
data.TokenDecimals = string(values[2])
|
||||
data.ContractAddress = string(values[3])
|
||||
data.TokenSymbol = values[0]
|
||||
data.Balance = values[1]
|
||||
data.TokenDecimals = values[2]
|
||||
data.ContractAddress = values[3]
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.grassecon.net/urdt/ussd/internal/storage"
|
||||
@@ -126,18 +127,12 @@ func TestStoreTemporaryVoucher(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify stored data
|
||||
expectedEntries := map[DataTyp][]byte{
|
||||
DATA_TEMPORARY_SYM: []byte("SRF"),
|
||||
DATA_TEMPORARY_BAL: []byte("200"),
|
||||
DATA_TEMPORARY_DECIMAL: []byte("6"),
|
||||
DATA_TEMPORARY_ADDRESS: []byte("0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9"),
|
||||
}
|
||||
expectedData := fmt.Sprintf("%s,%s,%s,%s", "SRF", "200", "6", "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9")
|
||||
|
||||
storedValue, err := store.ReadEntry(ctx, sessionId, DATA_TEMPORARY_VALUE)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedData, string(storedValue), "Mismatch for key %v", DATA_TEMPORARY_VALUE)
|
||||
|
||||
for key, expectedValue := range expectedEntries {
|
||||
storedValue, err := store.ReadEntry(ctx, sessionId, key)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedValue, storedValue, "Mismatch for key %v", key)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTemporaryVoucherData(t *testing.T) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"input": "5",
|
||||
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n3:Guard my PIN\n0:Back"
|
||||
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back"
|
||||
},
|
||||
{
|
||||
"input": "1",
|
||||
|
||||
1
services/registration/confirm_others_new_pin
Normal file
1
services/registration/confirm_others_new_pin
Normal file
@@ -0,0 +1 @@
|
||||
Please confirm new PIN for:{{.retrieve_blocked_number}}
|
||||
14
services/registration/confirm_others_new_pin.vis
Normal file
14
services/registration/confirm_others_new_pin.vis
Normal file
@@ -0,0 +1,14 @@
|
||||
CATCH pin_entry flag_incorrect_pin 1
|
||||
RELOAD retrieve_blocked_number
|
||||
MAP retrieve_blocked_number
|
||||
CATCH invalid_others_pin flag_valid_pin 0
|
||||
CATCH pin_reset_result flag_account_authorized 1
|
||||
LOAD save_others_temporary_pin 6
|
||||
RELOAD save_others_temporary_pin
|
||||
MOUT back 0
|
||||
HALT
|
||||
INCMP _ 0
|
||||
LOAD check_pin_mismatch 0
|
||||
RELOAD check_pin_mismatch
|
||||
CATCH others_pin_mismatch flag_pin_mismatch 1
|
||||
INCMP pin_entry *
|
||||
@@ -3,5 +3,3 @@ MOUT back 0
|
||||
HALT
|
||||
INCMP _ 0
|
||||
INCMP * pin_reset_success
|
||||
|
||||
|
||||
|
||||
1
services/registration/enter_other_number
Normal file
1
services/registration/enter_other_number
Normal file
@@ -0,0 +1 @@
|
||||
Enter other's phone number:
|
||||
7
services/registration/enter_other_number.vis
Normal file
7
services/registration/enter_other_number.vis
Normal file
@@ -0,0 +1,7 @@
|
||||
CATCH no_admin_privilege flag_admin_privilege 0
|
||||
LOAD reset_account_authorized 0
|
||||
RELOAD reset_account_authorized
|
||||
MOUT back 0
|
||||
HALT
|
||||
INCMP _ 0
|
||||
INCMP enter_others_new_pin *
|
||||
1
services/registration/enter_others_new_pin
Normal file
1
services/registration/enter_others_new_pin
Normal file
@@ -0,0 +1 @@
|
||||
Please enter new PIN for: {{.retrieve_blocked_number}}
|
||||
12
services/registration/enter_others_new_pin.vis
Normal file
12
services/registration/enter_others_new_pin.vis
Normal file
@@ -0,0 +1,12 @@
|
||||
LOAD validate_blocked_number 6
|
||||
RELOAD validate_blocked_number
|
||||
CATCH unregistered_number flag_unregistered_number 1
|
||||
LOAD retrieve_blocked_number 0
|
||||
RELOAD retrieve_blocked_number
|
||||
MAP retrieve_blocked_number
|
||||
MOUT back 0
|
||||
HALT
|
||||
LOAD verify_new_pin 6
|
||||
RELOAD verify_new_pin
|
||||
INCMP _ 0
|
||||
INCMP * confirm_others_new_pin
|
||||
@@ -1 +0,0 @@
|
||||
Guard my PIN
|
||||
@@ -1 +0,0 @@
|
||||
Linda PIN yangu
|
||||
1
services/registration/invalid_others_pin
Normal file
1
services/registration/invalid_others_pin
Normal file
@@ -0,0 +1 @@
|
||||
The PIN you have entered is invalid.Please try a 4 digit number instead.
|
||||
5
services/registration/invalid_others_pin.vis
Normal file
5
services/registration/invalid_others_pin.vis
Normal file
@@ -0,0 +1,5 @@
|
||||
MOUT retry 1
|
||||
MOUT quit 9
|
||||
HALT
|
||||
INCMP enter_others_new_pin 1
|
||||
INCMP quit 9
|
||||
1
services/registration/no_admin_privilege
Normal file
1
services/registration/no_admin_privilege
Normal file
@@ -0,0 +1 @@
|
||||
You do not have privileges to perform this action
|
||||
5
services/registration/no_admin_privilege.vis
Normal file
5
services/registration/no_admin_privilege.vis
Normal file
@@ -0,0 +1,5 @@
|
||||
MOUT quit 9
|
||||
MOUT back 0
|
||||
HALT
|
||||
INCMP pin_management 0
|
||||
INCMP quit 9
|
||||
1
services/registration/others_pin_mismatch
Normal file
1
services/registration/others_pin_mismatch
Normal file
@@ -0,0 +1 @@
|
||||
The PIN you have entered is not a match
|
||||
5
services/registration/others_pin_mismatch.vis
Normal file
5
services/registration/others_pin_mismatch.vis
Normal file
@@ -0,0 +1,5 @@
|
||||
MOUT retry 1
|
||||
MOUT quit 9
|
||||
HALT
|
||||
INCMP _ 1
|
||||
INCMP quit 9
|
||||
@@ -1,8 +1,8 @@
|
||||
MOUT change_pin 1
|
||||
MOUT reset_pin 2
|
||||
MOUT guard_pin 3
|
||||
MOUT back 0
|
||||
HALT
|
||||
INCMP _ 0
|
||||
INCMP my_account 0
|
||||
INCMP old_pin 1
|
||||
|
||||
INCMP enter_other_number 2
|
||||
INCMP . *
|
||||
|
||||
1
services/registration/pin_reset_result
Normal file
1
services/registration/pin_reset_result
Normal file
@@ -0,0 +1 @@
|
||||
PIN reset request for {{.retrieve_blocked_number}} was successful
|
||||
8
services/registration/pin_reset_result.vis
Normal file
8
services/registration/pin_reset_result.vis
Normal file
@@ -0,0 +1,8 @@
|
||||
LOAD retrieve_blocked_number 0
|
||||
MAP retrieve_blocked_number
|
||||
LOAD reset_others_pin 6
|
||||
MOUT back 0
|
||||
MOUT quit 9
|
||||
HALT
|
||||
INCMP pin_management 0
|
||||
INCMP quit 9
|
||||
@@ -6,5 +6,3 @@ MOUT quit 9
|
||||
HALT
|
||||
INCMP main 0
|
||||
INCMP quit 9
|
||||
|
||||
|
||||
|
||||
@@ -17,3 +17,5 @@ flag,flag_incorrect_date_format,23,this is set when the given year of birth is i
|
||||
flag,flag_incorrect_voucher,24,this is set when the selected voucher is invalid
|
||||
flag,flag_api_call_error,25,this is set when communication to an external service fails
|
||||
flag,flag_no_active_voucher,26,this is set when a user does not have an active voucher
|
||||
flag,flag_admin_privilege,27,this is set when a user has admin privileges.
|
||||
flag,flag_unregistered_number,28,this is set when an unregistered phonenumber tries to perform an action
|
||||
|
||||
|
1
services/registration/unregistered_number
Normal file
1
services/registration/unregistered_number
Normal file
@@ -0,0 +1 @@
|
||||
The number you have entered is either not registered with Sarafu or is invalid.
|
||||
7
services/registration/unregistered_number.vis
Normal file
7
services/registration/unregistered_number.vis
Normal file
@@ -0,0 +1,7 @@
|
||||
LOAD reset_unregistered_number 0
|
||||
RELOAD reset_unregistered_number
|
||||
MOUT back 0
|
||||
MOUT quit 9
|
||||
HALT
|
||||
INCMP ^ 0
|
||||
INCMP quit 9
|
||||
Reference in New Issue
Block a user