Compare commits

..

No commits in common. "master" and "lash/dbtx" have entirely different histories.

61 changed files with 428 additions and 2315 deletions

View File

@ -1,16 +0,0 @@
/**
!/args
!/cmd/africastalking
!/cmd/ssh
!/config
!/debug
!/handlers
!/internal
!/profile
!/services
!/ssh
!/store
!/LICENSE
!/README.md
!/go.*
!/.env.example

View File

@ -18,6 +18,3 @@ DATA_URL_BASE=http://localhost:5006
#Language #Language
DEFAULT_LANGUAGE=eng DEFAULT_LANGUAGE=eng
LANGUAGES=eng, swa LANGUAGES=eng, swa
#Alias search domains
ALIAS_SEARCH_DOMAINS=sarafu.local, sarafu.eth

View File

@ -1,56 +0,0 @@
name: release
on:
push:
tags:
- "v*"
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Check out repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to GHCR Docker registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set outputs
run: |
echo "RELEASE_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV \
&& echo "RELEASE_SHORT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Build and push image
uses: docker/build-push-action@v2
with:
context: ./
file: ./Dockerfile
platforms: linux/amd64
push: true
build-args: |
BUILD=${{ env.RELEASE_SHORT_COMMIT }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
tags: |
ghcr.io/grassrootseconomics/sarafu-vise:latest
ghcr.io/grassrootseconomics/sarafu-vise:${{ env.RELEASE_TAG }}

View File

@ -1,50 +0,0 @@
FROM golang:1.23.4-bookworm AS build
ENV CGO_ENABLED=1
ARG BUILDPLATFORM
ARG TARGETPLATFORM
ARG BUILD=dev
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
libgdbm-dev \
git \
&& rm -rf /var/lib/apt/lists/*
RUN git clone https://git.defalsify.org/vise.git go-vise
COPY . ./sarafu-vise
WORKDIR /build/sarafu-vise/services/registration
RUN echo "Compiling go-vise files"
RUN make VISE_PATH=/build/go-vise -B
WORKDIR /build/sarafu-vise
RUN echo "Building on $BUILDPLATFORM, building for $TARGETPLATFORM"
RUN go mod download
RUN go build -tags logtrace,online -o sarafu-at -ldflags="-X main.build=${BUILD} -s -w" cmd/africastalking/main.go
RUN go build -tags logtrace,online -o sarafu-ssh -ldflags="-X main.build=${BUILD} -s -w" cmd/ssh/main.go
FROM debian:bookworm-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
libgdbm-dev \
ca-certificates \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /service
COPY --from=build /build/sarafu-vise/sarafu-at .
COPY --from=build /build/sarafu-vise/sarafu-ssh .
COPY --from=build /build/sarafu-vise/LICENSE .
COPY --from=build /build/sarafu-vise/README.md .
COPY --from=build /build/sarafu-vise/services ./services
COPY --from=build /build/sarafu-vise/.env.example .
RUN mv .env.example .env
EXPOSE 7123
EXPOSE 7122
CMD ["./sarafu-at"]

View File

@ -10,7 +10,7 @@ type LangVar struct {
v []lang.Language v []lang.Language
} }
func (lv *LangVar) Set(s string) error { func(lv *LangVar) Set(s string) error {
v, err := lang.LanguageFromCode(s) v, err := lang.LanguageFromCode(s)
if err != nil { if err != nil {
return err return err
@ -19,14 +19,16 @@ func (lv *LangVar) Set(s string) error {
return err return err
} }
func (lv *LangVar) String() string { func(lv *LangVar) String() string {
var s []string var s []string
for _, v := range lv.v { for _, v := range(lv.v) {
s = append(s, v.Code) s = append(s, v.Code)
} }
return strings.Join(s, ",") return strings.Join(s, ",")
} }
func (lv *LangVar) Langs() []lang.Language { func(lv *LangVar) Langs() []lang.Language {
return lv.v return lv.v
} }

View File

@ -12,18 +12,18 @@ import (
"syscall" "syscall"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/lang"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/lang"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/visedriver/request"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/visedriver/request"
at "git.grassecon.net/grassrootseconomics/visedriver-africastalking/africastalking"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args" "git.grassecon.net/grassrootseconomics/sarafu-vise/args"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services" "git.grassecon.net/grassrootseconomics/sarafu-vise/services"
at "git.grassecon.net/grassrootseconomics/visedriver-africastalking/africastalking"
) )
var ( var (
@ -46,10 +46,10 @@ func main() {
var langs args.LangVar var langs args.LangVar
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
flag.StringVar(&host, "h", config.Host(), "http host") flag.StringVar(&host, "h", config.Host(), "http host")
flag.UintVar(&port, "p", config.Port(), "http port") flag.UintVar(&port, "p", config.Port(), "http port")
@ -81,7 +81,6 @@ func main() {
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true,
} }
if engineDebug { if engineDebug {
@ -119,7 +118,7 @@ func main() {
} }
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
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)
@ -134,7 +133,6 @@ func main() {
rp := &at.ATRequestParser{} rp := &at.ATRequestParser{}
bsh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl) bsh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl)
bsh = bsh.WithEngineFunc(lhs.GetEngine)
sh := at.NewATRequestHandler(bsh) sh := at.NewATRequestHandler(bsh)
mux := http.NewServeMux() mux := http.NewServeMux()

View File

@ -1,15 +1,12 @@
package main package main
import ( import (
"bufio"
"context" "context"
"flag" "flag"
"fmt" "fmt"
"io"
"os" "os"
"os/signal" "os/signal"
"path" "path"
"strings"
"syscall" "syscall"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
@ -17,12 +14,12 @@ import (
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/visedriver/request"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/visedriver/request"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
) )
var ( var (
@ -58,10 +55,10 @@ func main() {
var langs args.LangVar var langs args.LangVar
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
@ -96,7 +93,6 @@ func main() {
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true,
} }
if engineDebug { if engineDebug {
@ -131,6 +127,7 @@ func main() {
lhs.SetDataStore(&userdataStore) lhs.SetDataStore(&userdataStore)
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
hl, err := lhs.GetHandler(accountService) hl, err := lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
@ -148,8 +145,6 @@ func main() {
sessionId: sessionId, sessionId: sessionId,
} }
sh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl) sh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl)
sh = sh.WithEngineFunc(lhs.GetEngine)
cfg.SessionId = sessionId cfg.SessionId = sessionId
rqs := request.RequestSession{ rqs := request.RequestSession{
Ctx: ctx, Ctx: ctx,
@ -189,19 +184,11 @@ func main() {
os.Exit(1) os.Exit(1)
} }
fmt.Println("") fmt.Println("")
in := bufio.NewReader(os.Stdin) _, err = fmt.Scanln(&rqs.Input)
s, err := in.ReadString('\n')
if err != nil { if err != nil {
if err == io.EOF {
logg.DebugCtxf(ctx, "have EOF, bailing")
break
}
logg.ErrorCtxf(ctx, "error in input", "err", err) logg.ErrorCtxf(ctx, "error in input", "err", err)
fmt.Errorf("error in input: %v", err) fmt.Errorf("error in input: %v", err)
os.Exit(1) os.Exit(1)
} }
rqs.Input = []byte{}
s = strings.TrimSpace(s)
rqs.Input = []byte(s)
} }
} }

View File

@ -17,13 +17,13 @@ import (
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/visedriver/request"
httprequest "git.grassecon.net/grassrootseconomics/visedriver/request/http" httprequest "git.grassecon.net/grassrootseconomics/visedriver/request/http"
"git.grassecon.net/grassrootseconomics/visedriver/request"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args" "git.grassecon.net/grassrootseconomics/sarafu-vise/args"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
) )
var ( var (
@ -44,10 +44,10 @@ func main() {
var gettextDir string var gettextDir string
var langs args.LangVar var langs args.LangVar
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
@ -82,7 +82,6 @@ func main() {
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
ResetOnEmptyInput: true,
} }
if engineDebug { if engineDebug {
@ -117,7 +116,7 @@ func main() {
} }
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
hl, err := lhs.GetHandler(accountService) hl, err := lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
@ -134,7 +133,6 @@ func main() {
rp := &httprequest.DefaultRequestParser{} rp := &httprequest.DefaultRequestParser{}
bsh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl) bsh := request.NewBaseRequestHandler(cfg, rs, stateStore, userdataStore, rp, hl)
bsh = bsh.WithEngineFunc(lhs.GetEngine)
sh := httprequest.NewHTTPRequestHandler(bsh) sh := httprequest.NewHTTPRequestHandler(bsh)
s := &http.Server{ s := &http.Server{
Addr: fmt.Sprintf("%s:%s", host, strconv.Itoa(int(port))), Addr: fmt.Sprintf("%s:%s", host, strconv.Itoa(int(port))),

View File

@ -10,14 +10,14 @@ import (
"syscall" "syscall"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/lang"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args" "git.defalsify.org/vise.git/lang"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/sarafu-vise/args"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
) )
var ( var (
@ -38,10 +38,10 @@ func main() {
var langs args.LangVar var langs args.LangVar
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory") flag.StringVar(&gettextDir, "gettext", "", "use gettext translations from given directory")
@ -62,6 +62,7 @@ func main() {
} }
ctx := context.Background() ctx := context.Background()
ctx = context.WithValue(ctx, "SessionId", sessionId)
ln, err := lang.LanguageFromCode(config.Language()) ln, err := lang.LanguageFromCode(config.Language())
if err != nil { if err != nil {
@ -73,13 +74,11 @@ func main() {
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
cfg := engine.Config{ cfg := engine.Config{
Root: "root", Root: "root",
SessionId: sessionId, SessionId: sessionId,
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
MenuSeparator: menuSeparator, MenuSeparator: menuSeparator,
EngineDebug: engineDebug,
ResetOnEmptyInput: true,
} }
menuStorageService := storage.NewMenuStorageService(conns) menuStorageService := storage.NewMenuStorageService(conns)
@ -87,7 +86,7 @@ func main() {
fmt.Fprintf(os.Stderr, "menu storage service error: %v\n", err) fmt.Fprintf(os.Stderr, "menu storage service error: %v\n", err)
os.Exit(1) os.Exit(1)
} }
if gettextDir != "" { if gettextDir != "" {
menuStorageService = menuStorageService.WithGettext(gettextDir, langs.Langs()) menuStorageService = menuStorageService.WithGettext(gettextDir, langs.Langs())
} }
@ -125,26 +124,28 @@ func main() {
} }
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
_, err = lhs.GetHandler(accountService) hl, err := lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err) fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err)
os.Exit(1) os.Exit(1)
} }
en := lhs.GetEngine(cfg, rs, pe)
en := lhs.GetEngine()
en = en.WithFirst(hl.Init)
if engineDebug {
en = en.WithDebug(nil)
}
cint := make(chan os.Signal) cint := make(chan os.Signal)
cterm := make(chan os.Signal) cterm := make(chan os.Signal)
signal.Notify(cint, os.Interrupt, syscall.SIGINT) signal.Notify(cint, os.Interrupt, syscall.SIGINT)
signal.Notify(cterm, os.Interrupt, syscall.SIGTERM) signal.Notify(cterm, os.Interrupt, syscall.SIGTERM)
go func() { go func() {
var s os.Signal
select { select {
case s = <-cterm: case _ = <-cint:
case s = <-cint: case _ = <-cterm:
} }
logg.InfoCtxf(ctx, "stopping on signal", "sig", s) menuStorageService.Close(ctx)
en.Finish(ctx)
os.Exit(0)
}() }()
err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil)

View File

@ -31,25 +31,25 @@ var (
func main() { func main() {
config.LoadConfig() config.LoadConfig()
override := config.NewOverride() var override config.Override
var authConnStr string var authConnStr string
var size uint var size uint
var engineDebug bool var engineDebug bool
var stateDebug bool var stateDebug bool
var host string var host string
var port uint var port uint
//flag.StringVar(&authConnStr, "authdb", "", "auth connection string")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource connection string") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.UintVar(&size, "s", 160, "max size of output") flag.UintVar(&size, "s", 160, "max size of output")
flag.StringVar(&host, "h", config.HostSSH(), "socket host") flag.StringVar(&host, "h", config.HostSSH(), "socket host")
flag.UintVar(&port, "p", config.PortSSH(), "socket port") flag.UintVar(&port, "p", config.PortSSH(), "socket port")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(&override)
conns, err := config.GetConns() conns, err := config.GetConns()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err) fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err)
@ -84,7 +84,6 @@ func main() {
Root: "root", Root: "root",
OutputSize: uint32(size), OutputSize: uint32(size),
FlagCount: uint32(128), FlagCount: uint32(128),
ResetOnEmptyInput: true,
} }
if stateDebug { if stateDebug {
cfg.StateDebug = true cfg.StateDebug = true
@ -112,13 +111,13 @@ func main() {
signal.Notify(cterm, os.Interrupt, syscall.SIGTERM) signal.Notify(cterm, os.Interrupt, syscall.SIGTERM)
runner := &ssh.SshRunner{ runner := &ssh.SshRunner{
Cfg: cfg, Cfg: cfg,
Debug: engineDebug, Debug: engineDebug,
FlagFile: pfp, FlagFile: pfp,
Conn: conns, Conn: conns,
SrvKeyFile: sshKeyFile, SrvKeyFile: sshKeyFile,
Host: host, Host: host,
Port: port, Port: port,
} }
go func() { go func() {
select { select {

View File

@ -2,19 +2,30 @@ package config
import ( import (
viseconfig "git.grassecon.net/grassrootseconomics/visedriver/config" viseconfig "git.grassecon.net/grassrootseconomics/visedriver/config"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
) )
func NewOverride() *viseconfig.Override { type Override struct {
o := &viseconfig.Override{ DbConn *string
StateConnMode: storage.DBMODE_TEXT, StateConn *string
ResourceConnMode: storage.DBMODE_TEXT, ResourceConn *string
UserConnMode: storage.DBMODE_BINARY, UserConn *string
}
func NewOverride() *Override {
var a string
var b string
var c string
var d string
o := &Override{
DbConn: &a,
StateConn: &b,
ResourceConn: &c,
UserConn: &d,
} }
return o return o
} }
func Apply(o *viseconfig.Override) error { func Apply(o *Override) error {
viseconfig.ApplyConn(o) viseconfig.ApplyConn(o.DbConn, o.StateConn, o.ResourceConn, o.UserConn)
return nil return nil
} }

View File

@ -1,16 +1,14 @@
package config package config
import ( import (
"strings"
apiconfig "git.grassecon.net/grassrootseconomics/sarafu-api/config"
viseconfig "git.grassecon.net/grassrootseconomics/visedriver/config"
"git.grassecon.net/grassrootseconomics/visedriver/env" "git.grassecon.net/grassrootseconomics/visedriver/env"
viseconfig "git.grassecon.net/grassrootseconomics/visedriver/config"
apiconfig "git.grassecon.net/grassrootseconomics/sarafu-api/config"
) )
var ( var (
GetConns = viseconfig.GetConns GetConns = viseconfig.GetConns
EnvPath string EnvPath string
) )
func loadEnv() { func loadEnv() {
@ -22,11 +20,10 @@ func loadEnv() {
} }
const ( const (
defaultSSHHost string = "127.0.0.1" defaultSSHHost string = "127.0.0.1"
defaultSSHPort uint = 7122 defaultSSHPort uint = 7122
defaultHTTPHost string = "127.0.0.1" defaultHTTPHost string = "127.0.0.1"
defaultHTTPPort uint = 7123 defaultHTTPPort uint = 7123
defaultDomain = "sarafu.local"
) )
func LoadConfig() error { func LoadConfig() error {
@ -42,17 +39,6 @@ func LoadConfig() error {
return nil return nil
} }
func SearchDomains() []string {
var ParsedDomains []string
SearchDomains := env.GetEnv("ALIAS_SEARCH_DOMAINS", defaultDomain)
SearchDomainList := strings.Split(env.GetEnv("ALIAS_SEARCH_DOMAINS", SearchDomains), ",")
for _, domain := range SearchDomainList {
ParsedDomains = append(ParsedDomains, strings.ReplaceAll(domain, " ", ""))
}
return ParsedDomains
}
func Language() string { func Language() string {
return viseconfig.DefaultLanguage return viseconfig.DefaultLanguage
} }

View File

@ -1,11 +1,11 @@
package debug package debug
import ( import (
"encoding/binary"
"fmt" "fmt"
"encoding/binary"
visedb "git.defalsify.org/vise.git/db"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
visedb "git.defalsify.org/vise.git/db"
) )
var ( var (
@ -13,10 +13,10 @@ var (
) )
type KeyInfo struct { type KeyInfo struct {
SessionId string SessionId string
Typ uint8 Typ uint8
SubTyp storedb.DataTyp SubTyp storedb.DataTyp
Label string Label string
Description string Description string
} }
@ -53,11 +53,12 @@ func ToKeyInfo(k []byte, sessionId string) (KeyInfo, error) {
k = k[2:] k = k[2:]
} }
return o, nil return o, nil
} }
func subTypToString(v storedb.DataTyp) string { func subTypToString(v storedb.DataTyp) string {
return dbTypStr[v+visedb.DATATYPE_USERDATA+1] return dbTypStr[v + visedb.DATATYPE_USERDATA + 1]
} }
func typToString(v uint8) string { func typToString(v uint8) string {

View File

@ -1,4 +1,3 @@
//go:build debugdb
// +build debugdb // +build debugdb
package debug package debug
@ -12,37 +11,37 @@ import (
func init() { func init() {
DebugCap |= 1 DebugCap |= 1
dbTypStr[db.DATATYPE_STATE] = "internal state" dbTypStr[db.DATATYPE_STATE] = "internal state"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TRACKING_ID] = "tracking id" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TRACKING_ID] = "tracking id"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_PUBLIC_KEY] = "public key" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_PUBLIC_KEY] = "public key"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_ACCOUNT_PIN] = "account pin" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_ACCOUNT_PIN] = "account pin"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_FIRST_NAME] = "first name" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_FIRST_NAME] = "first name"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_FAMILY_NAME] = "family name" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_FAMILY_NAME] = "family name"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_YOB] = "year of birth" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_YOB] = "year of birth"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_LOCATION] = "location" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_LOCATION] = "location"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_GENDER] = "gender" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_GENDER] = "gender"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_OFFERINGS] = "offerings" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_OFFERINGS] = "offerings"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_RECIPIENT] = "recipient" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_RECIPIENT] = "recipient"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_AMOUNT] = "amount" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_AMOUNT] = "amount"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TEMPORARY_VALUE] = "temporary value" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TEMPORARY_VALUE] = "temporary value"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_ACTIVE_SYM] = "active sym" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_ACTIVE_SYM] = "active sym"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_ACTIVE_BAL] = "active bal" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_ACTIVE_BAL] = "active bal"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_BLOCKED_NUMBER] = "blocked number" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_BLOCKED_NUMBER] = "blocked number"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_PUBLIC_KEY_REVERSE] = "public_key_reverse" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_PUBLIC_KEY_REVERSE] = "public_key_reverse"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_ACTIVE_DECIMAL] = "active decimal" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_ACTIVE_DECIMAL] = "active decimal"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_ACTIVE_ADDRESS] = "active address" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_ACTIVE_ADDRESS] = "active address"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_INCORRECT_PIN_ATTEMPTS] = "incorrect pin attempts" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_INCORRECT_PIN_ATTEMPTS] = "incorrect pin attempts"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_SELECTED_LANGUAGE_CODE] = "selected language" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_SELECTED_LANGUAGE_CODE] = "selected language"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_INITIAL_LANGUAGE_CODE] = "initial language" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_INITIAL_LANGUAGE_CODE] = "initial language"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_VOUCHER_SYMBOLS] = "voucher symbols" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_VOUCHER_SYMBOLS] = "voucher symbols"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_VOUCHER_BALANCES] = "voucher balances" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_VOUCHER_BALANCES] = "voucher balances"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_VOUCHER_DECIMALS] = "voucher decimals" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_VOUCHER_DECIMALS] = "voucher decimals"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_VOUCHER_ADDRESSES] = "voucher addresses" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_VOUCHER_ADDRESSES] = "voucher addresses"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_SENDERS] = "tx senders" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_SENDERS] = "tx senders"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_RECIPIENTS] = "tx recipients" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_RECIPIENTS] = "tx recipients"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_VALUES] = "tx values" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_VALUES] = "tx values"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_ADDRESSES] = "tx addresses" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_ADDRESSES] = "tx addresses"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_HASHES] = "tx hashes" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_HASHES] = "tx hashes"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_DATES] = "tx dates" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_DATES] = "tx dates"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_SYMBOLS] = "tx symbols" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_SYMBOLS] = "tx symbols"
dbTypStr[db.DATATYPE_USERDATA+1+storedb.DATA_TX_DECIMALS] = "tx decimals" dbTypStr[db.DATATYPE_USERDATA + 1 + storedb.DATA_TX_DECIMALS] = "tx decimals"
} }

View File

@ -3,8 +3,8 @@ package debug
import ( import (
"testing" "testing"
visedb "git.defalsify.org/vise.git/db"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
visedb "git.defalsify.org/vise.git/db"
) )
func TestDebugDbSubKeyInfo(t *testing.T) { func TestDebugDbSubKeyInfo(t *testing.T) {
@ -24,7 +24,7 @@ func TestDebugDbSubKeyInfo(t *testing.T) {
if r.SubTyp != 2 { if r.SubTyp != 2 {
t.Fatalf("expected 2, got %d", r.SubTyp) t.Fatalf("expected 2, got %d", r.SubTyp)
} }
if DebugCap&1 > 0 { if DebugCap & 1 > 0 {
if r.Label != "tracking id" { if r.Label != "tracking id" {
t.Fatalf("expected 'tracking id', got '%s'", r.Label) t.Fatalf("expected 'tracking id', got '%s'", r.Label)
} }
@ -45,7 +45,7 @@ func TestDebugDbKeyInfo(t *testing.T) {
if r.Typ != 16 { if r.Typ != 16 {
t.Fatalf("expected 16, got %d", r.Typ) t.Fatalf("expected 16, got %d", r.Typ)
} }
if DebugCap&1 > 0 { if DebugCap & 1 > 0 {
if r.Label != "internal state" { if r.Label != "internal state" {
t.Fatalf("expected 'internal_state', got '%s'", r.Label) t.Fatalf("expected 'internal_state', got '%s'", r.Label)
} }
@ -68,7 +68,7 @@ func TestDebugDbKeyInfoRestore(t *testing.T) {
if r.Typ != 32 { if r.Typ != 32 {
t.Fatalf("expected 32, got %d", r.Typ) t.Fatalf("expected 32, got %d", r.Typ)
} }
if DebugCap&1 > 0 { if DebugCap & 1 > 0 {
if r.Label != "active sym" { if r.Label != "active sym" {
t.Fatalf("expected 'active sym', got '%s'", r.Label) t.Fatalf("expected 'active sym', got '%s'", r.Label)
} }

View File

@ -10,31 +10,30 @@ import (
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
"git.grassecon.net/grassrootseconomics/sarafu-vise/internal/cmd"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/internal/cmd"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
) )
var ( var (
logg = logging.NewVanilla().WithContextKey("SessionId") logg = logging.NewVanilla().WithContextKey("SessionId")
scriptDir = path.Join("services", "registration") scriptDir = path.Join("services", "registration")
) )
func main() { func main() {
config.LoadConfig() config.LoadConfig()
override := config.NewOverride()
var sessionId string var sessionId string
var override config.Override
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(&override)
conns, err := config.GetConns() conns, err := config.GetConns()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err) fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err)
@ -42,6 +41,7 @@ func main() {
} }
ctx := context.Background() ctx := context.Background()
ctx = context.WithValue(ctx, "SessionId", sessionId)
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
flagParser, err := application.NewFlagManager(pfp) flagParser, err := application.NewFlagManager(pfp)

View File

@ -8,17 +8,18 @@ import (
"path" "path"
"strings" "strings"
"git.defalsify.org/vise.git/lang"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/lang"
"git.grassecon.net/grassrootseconomics/visedriver/config" "git.grassecon.net/grassrootseconomics/visedriver/config"
) )
const ( const (
changeHeadSrc = `LOAD reset_account_authorized 0 changeHeadSrc = `LOAD reset_account_authorized 0
LOAD reset_incorrect 0 LOAD reset_incorrect 0
CATCH incorrect_pin flag_incorrect_pin 1 CATCH incorrect_pin flag_incorrect_pin 1
CATCH pin_entry flag_account_authorized 0 CATCH pin_entry flag_account_authorized 0
` `
selectSrc = `LOAD set_language 6 selectSrc = `LOAD set_language 6
RELOAD set_language RELOAD set_language
@ -28,8 +29,8 @@ MOVE language_changed
) )
var ( var (
logg = logging.NewVanilla() logg = logging.NewVanilla()
mouts string mouts string
incmps string incmps string
) )
@ -62,7 +63,7 @@ func main() {
} }
logg.Tracef("using languages", "lang", config.Languages) logg.Tracef("using languages", "lang", config.Languages)
for i, v := range config.Languages { for i, v := range(config.Languages) {
ln, err := lang.LanguageFromCode(v) ln, err := lang.LanguageFromCode(v)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error parsing language: %s\n", v) fmt.Fprintf(os.Stderr, "error parsing language: %s\n", v)
@ -75,7 +76,7 @@ func main() {
incmps += fmt.Sprintf("INCMP %s %v\n", v, n) incmps += fmt.Sprintf("INCMP %s %v\n", v, n)
p := path.Join(srcDir, v) p := path.Join(srcDir, v)
w, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) w, err := os.OpenFile(p, os.O_WRONLY | os.O_CREATE | os.O_EXCL, 0600)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "failed open language set template output: %v\n", err) fmt.Fprintf(os.Stderr, "failed open language set template output: %v\n", err)
os.Exit(1) os.Exit(1)
@ -92,7 +93,7 @@ func main() {
src += "INCMP . *\n" src += "INCMP . *\n"
p := path.Join(srcDir, "select_language.vis") p := path.Join(srcDir, "select_language.vis")
w, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) w, err := os.OpenFile(p, os.O_WRONLY | os.O_CREATE | os.O_EXCL, 0600)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "failed open select language vis output: %v\n", err) fmt.Fprintf(os.Stderr, "failed open select language vis output: %v\n", err)
os.Exit(1) os.Exit(1)
@ -106,7 +107,7 @@ func main() {
src = changeHeadSrc + src src = changeHeadSrc + src
p = path.Join(srcDir, "change_language.vis") p = path.Join(srcDir, "change_language.vis")
w, err = os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) w, err = os.OpenFile(p, os.O_WRONLY | os.O_CREATE | os.O_EXCL, 0600)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "failed open select language vis output: %v\n", err) fmt.Fprintf(os.Stderr, "failed open select language vis output: %v\n", err)
os.Exit(1) os.Exit(1)

View File

@ -7,11 +7,11 @@ import (
"os" "os"
"path" "path"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/debug"
"git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/db"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/debug"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
) )
var ( var (
@ -32,7 +32,7 @@ func formatItem(k []byte, v []byte, sessionId string) (string, error) {
func main() { func main() {
config.LoadConfig() config.LoadConfig()
override := config.NewOverride() var override config.Override
var sessionId string var sessionId string
var database string var database string
var engineDebug bool var engineDebug bool
@ -40,14 +40,14 @@ func main() {
var first bool var first bool
flag.StringVar(&sessionId, "session-id", "075xx2123", "session id") flag.StringVar(&sessionId, "session-id", "075xx2123", "session id")
flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)")
flag.StringVar(&override.ResourceConn, "resource", "?", "resource data directory") flag.StringVar(override.ResourceConn, "resource", "?", "resource connection string")
flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") flag.StringVar(override.UserConn, "userdata", "?", "userdata store connection string")
flag.StringVar(&override.StateConn, "state", "?", "state store connection string") flag.StringVar(override.StateConn, "state", "?", "state store connection string")
flag.BoolVar(&engineDebug, "d", false, "use engine debug output") flag.BoolVar(&engineDebug, "d", false, "use engine debug output")
flag.Parse() flag.Parse()
config.Apply(override) config.Apply(&override)
conns, err := config.GetConns() conns, err := config.GetConns()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err) fmt.Fprintf(os.Stderr, "conn specification error: %v\n", err)

8
go.mod
View File

@ -3,11 +3,11 @@ module git.grassecon.net/grassrootseconomics/sarafu-vise
go 1.23.4 go 1.23.4
require ( require (
git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69 git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250121135150-e0b539809805
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250121134912-f7d31e4e8162
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250121135340-ca97e23e8c84
github.com/alecthomas/assert/v2 v2.2.2 github.com/alecthomas/assert/v2 v2.2.2
github.com/gofrs/uuid v4.4.0+incompatible github.com/gofrs/uuid v4.4.0+incompatible
github.com/grassrootseconomics/ussd-data-service v1.2.0-beta github.com/grassrootseconomics/ussd-data-service v1.2.0-beta

16
go.sum
View File

@ -1,13 +1,13 @@
git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac h1:f/E0ZTclVfMEnD/3Alrzzbg+dOm138zGydV42jT0JPw= git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9 h1:sPcqXQcywxA8W3W+9qQncLPmsrgqTIlec7vmD4/7vyA=
git.defalsify.org/vise.git v0.2.3-0.20250205173834-d1f6647211ac/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= git.defalsify.org/vise.git v0.2.3-0.20250120121301-10739fb4a8c9/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d h1:5mzLas+jxTUtusOKx4XvU+n2QvrV/mH17MnJRy46siQ= git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d h1:5mzLas+jxTUtusOKx4XvU+n2QvrV/mH17MnJRy46siQ=
git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60= git.grassecon.net/grassrootseconomics/common v0.0.0-20250121134736-ba8cbbccea7d/go.mod h1:wgQJZGIS6QuNLHqDhcsvehsbn5PvgV7aziRebMnJi60=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69 h1:cbBpm9uNJak58MpFpNXJuvgCmz+A8kquXr9har4expg= git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250121135150-e0b539809805 h1:deGnqf4YCsbxhXgjFEjYjTUCvciLEmI26T9IysRsQXY=
git.grassecon.net/grassrootseconomics/sarafu-api v0.9.0-beta.1.0.20250206112944-31eb30de0f69/go.mod h1:gOn89ipaDcDvmQXRMQYKUqcw/sJcwVOPVt2eC6Geip8= git.grassecon.net/grassrootseconomics/sarafu-api v0.0.0-20250121135150-e0b539809805/go.mod h1:9bc3d//Qqm11hz7GYRdQc1Uan+0GJIOpvRBbv8cHMu8=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244 h1:BXotWSKg04U97sf/xeWJuUTSVgKk2aEK+5BtBrnafXQ= git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250121134912-f7d31e4e8162 h1:NaPbgGQ1Nb+yYF+Qj1LSagpjYeDcSXST8iZwONg4afY=
git.grassecon.net/grassrootseconomics/visedriver v0.9.0-beta.1.0.20250204132347-1eb0b1555244/go.mod h1:6B6ByxXOiRY0NR7K02Bf3fEu7z+2c/6q8PFVNjC5G8w= git.grassecon.net/grassrootseconomics/visedriver v0.8.0-beta.10.0.20250121134912-f7d31e4e8162/go.mod h1:pjKp9L/ZsWW3kMB0UoIl1yv9TBIuU33mn9Aghxp7vGk=
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694 h1:DjJlBSz0S13acft5XZDWk7ZYnzElym0xLMYEVgyNJ+E= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250121135340-ca97e23e8c84 h1:VoBmqsjlRdz+IPbtKsAkc1IrMepjR+QlesZT31Jokrk=
git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250129070628-5a539172c694/go.mod h1:DpibtYpnT3nG4Kn556hRAkdu4+CtiI/6MbnQHal51mQ= git.grassecon.net/grassrootseconomics/visedriver-africastalking v0.0.0-20250121135340-ca97e23e8c84/go.mod h1:DpibtYpnT3nG4Kn556hRAkdu4+CtiI/6MbnQHal51mQ=
github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk=
github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g=

View File

@ -23,9 +23,7 @@ import (
"git.grassecon.net/grassrootseconomics/common/person" "git.grassecon.net/grassrootseconomics/common/person"
"git.grassecon.net/grassrootseconomics/common/phone" "git.grassecon.net/grassrootseconomics/common/phone"
"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/remote" "git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"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"
@ -102,12 +100,14 @@ func NewMenuHandlers(appFlags *FlagManager, userdataStore db.Db, accountService
return h, nil return h, nil
} }
// SetPersister sets persister instance to the handlers. // WithPersister 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.
@ -123,6 +123,12 @@ func (h *MenuHandlers) Init(ctx context.Context, sym string, input []byte) (reso
h.st = h.pe.GetState() h.st = h.pe.GetState()
h.ca = h.pe.GetMemory() h.ca = h.pe.GetMemory()
if len(input) == 0 {
// move to the top node
h.st.Code = []byte{}
}
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if ok { if ok {
ctx = context.WithValue(ctx, "SessionId", sessionId) ctx = context.WithValue(ctx, "SessionId", sessionId)
@ -267,7 +273,7 @@ func (h *MenuHandlers) CheckBlockedStatus(ctx context.Context, sym string, input
} }
pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64) pinAttemptsValue, _ := strconv.ParseUint(string(currentWrongPinAttempts), 0, 64)
if pinAttemptsValue == 0 { if pinAttemptsValue == 0 {
res.FlagReset = append(res.FlagReset, flag_account_blocked) res.FlagReset = append(res.FlagReset, flag_account_blocked)
return res, nil return res, nil
@ -318,16 +324,12 @@ func (h *MenuHandlers) VerifyNewPin(ctx context.Context, sym string, input []byt
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin") flag_valid_pin, _ := h.flagManager.GetFlag("flag_valid_pin")
if string(input) != "0" { pinInput := string(input)
pinInput := string(input) // Validate that the PIN is a 4-digit number.
// Validate that the PIN is a 4-digit number. if pin.IsValidPIN(pinInput) {
if pin.IsValidPIN(pinInput) {
res.FlagSet = append(res.FlagSet, flag_valid_pin)
} else {
res.FlagReset = append(res.FlagReset, flag_valid_pin)
}
} else {
res.FlagSet = append(res.FlagSet, flag_valid_pin) res.FlagSet = append(res.FlagSet, flag_valid_pin)
} else {
res.FlagReset = append(res.FlagReset, flag_valid_pin)
} }
return res, nil return res, nil
@ -384,12 +386,6 @@ func (h *MenuHandlers) SaveOthersTemporaryPin(ctx context.Context, sym string, i
} }
temporaryPin := string(input) temporaryPin := string(input)
// Validate that the input is a 4-digit number.
if !pin.IsValidPIN(temporaryPin) {
return res, nil
}
// Retrieve the blocked number associated with this session // Retrieve the blocked number associated with this session
blockedNumber, err := store.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER) blockedNumber, err := store.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER)
if err != nil { if err != nil {
@ -422,11 +418,6 @@ func (h *MenuHandlers) CheckBlockedNumPinMisMatch(ctx context.Context, sym strin
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
if string(input) == "0" {
res.FlagReset = append(res.FlagReset, flag_pin_mismatch)
return res, nil
}
// Get blocked number from storage. // Get blocked number from storage.
store := h.userdataStore store := h.userdataStore
blockedNumber, err := store.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER) blockedNumber, err := store.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER)
@ -440,11 +431,6 @@ func (h *MenuHandlers) CheckBlockedNumPinMisMatch(ctx context.Context, sym strin
logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
return res, err return res, err
} }
if len(hashedTemporaryPin) == 0 {
logg.ErrorCtxf(ctx, "hashedTemporaryPin is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) { if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) {
res.FlagReset = append(res.FlagReset, flag_pin_mismatch) res.FlagReset = append(res.FlagReset, flag_pin_mismatch)
} else { } else {
@ -462,21 +448,12 @@ func (h *MenuHandlers) ConfirmPinChange(ctx context.Context, sym string, input [
} }
flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch") flag_pin_mismatch, _ := h.flagManager.GetFlag("flag_pin_mismatch")
if string(input) == "0" {
res.FlagReset = append(res.FlagReset, flag_pin_mismatch)
return res, nil
}
store := h.userdataStore store := h.userdataStore
hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) hashedTemporaryPin, err := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
return res, err return res, err
} }
if len(hashedTemporaryPin) == 0 {
logg.ErrorCtxf(ctx, "hashedTemporaryPin is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) { if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) {
res.FlagReset = append(res.FlagReset, flag_pin_mismatch) res.FlagReset = append(res.FlagReset, flag_pin_mismatch)
@ -511,17 +488,13 @@ func (h *MenuHandlers) ResetOthersPin(ctx context.Context, sym string, input []b
logg.ErrorCtxf(ctx, "failed to read blockedPhonenumber entry with", "key", storedb.DATA_BLOCKED_NUMBER, "error", err) logg.ErrorCtxf(ctx, "failed to read blockedPhonenumber entry with", "key", storedb.DATA_BLOCKED_NUMBER, "error", err)
return res, err return res, err
} }
hashedTemporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), storedb.DATA_TEMPORARY_VALUE) hashedTmporaryPin, err := store.ReadEntry(ctx, string(blockedPhonenumber), storedb.DATA_TEMPORARY_VALUE)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to read hashedTmporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTmporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
return res, err return res, err
} }
if len(hashedTemporaryPin) == 0 {
logg.ErrorCtxf(ctx, "hashedTemporaryPin is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, string(blockedPhonenumber), storedb.DATA_ACCOUNT_PIN, []byte(hashedTemporaryPin)) err = store.WriteEntry(ctx, string(blockedPhonenumber), storedb.DATA_ACCOUNT_PIN, []byte(hashedTmporaryPin))
if err != nil { if err != nil {
return res, err return res, err
} }
@ -606,21 +579,12 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
if string(input) == "0" {
res.FlagReset = append(res.FlagReset, flag_unregistered_number)
return res, nil
}
blockedNumber := string(input) blockedNumber := string(input)
formattedNumber, err := phone.FormatPhoneNumber(blockedNumber) _, err = store.ReadEntry(ctx, blockedNumber, storedb.DATA_PUBLIC_KEY)
if err != nil { if !phone.IsValidPhoneNumber(blockedNumber) {
res.FlagSet = append(res.FlagSet, flag_unregistered_number) res.FlagSet = append(res.FlagSet, flag_unregistered_number)
logg.ErrorCtxf(ctx, "Failed to format the phone number: %s", blockedNumber, "error", err)
return res, nil return res, nil
} }
_, err = store.ReadEntry(ctx, formattedNumber, storedb.DATA_PUBLIC_KEY)
if err != nil { if err != nil {
if db.IsNotFound(err) { if db.IsNotFound(err) {
logg.InfoCtxf(ctx, "Invalid or unregistered number") logg.InfoCtxf(ctx, "Invalid or unregistered number")
@ -631,7 +595,7 @@ func (h *MenuHandlers) ValidateBlockedNumber(ctx context.Context, sym string, in
return res, err return res, err
} }
} }
err = store.WriteEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER, []byte(formattedNumber)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER, []byte(blockedNumber))
if err != nil { if err != nil {
return res, nil return res, nil
} }
@ -658,11 +622,6 @@ func (h *MenuHandlers) VerifyCreatePin(ctx context.Context, sym string, input []
logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err) logg.ErrorCtxf(ctx, "failed to read hashedTemporaryPin entry with", "key", storedb.DATA_TEMPORARY_VALUE, "error", err)
return res, err return res, err
} }
if len(hashedTemporaryPin) == 0 {
logg.ErrorCtxf(ctx, "hashedTemporaryPin is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) { if pin.VerifyPIN(string(hashedTemporaryPin), string(input)) {
res.FlagSet = []uint32{flag_valid_pin} res.FlagSet = []uint32{flag_valid_pin}
res.FlagReset = []uint32{flag_pin_mismatch} res.FlagReset = []uint32{flag_pin_mismatch}
@ -698,19 +657,11 @@ func (h *MenuHandlers) SaveFirstname(ctx context.Context, sym string, input []by
firstNameSet := h.st.MatchFlag(flag_firstname_set, true) firstNameSet := h.st.MatchFlag(flag_firstname_set, true)
if allowUpdate { if allowUpdate {
temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryFirstName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryFirstName) == 0 {
logg.ErrorCtxf(ctx, "temporaryFirstName is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_FIRST_NAME, []byte(temporaryFirstName)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_FIRST_NAME, []byte(temporaryFirstName))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write firstName entry with", "key", storedb.DATA_FIRST_NAME, "value", temporaryFirstName, "error", err) logg.ErrorCtxf(ctx, "failed to write firstName entry with", "key", storedb.DATA_FIRST_NAME, "value", temporaryFirstName, "error", err)
return res, err return res, err
} }
err := h.constructAccountAlias(ctx)
if err != nil {
return res, err
}
res.FlagSet = append(res.FlagSet, flag_firstname_set) res.FlagSet = append(res.FlagSet, flag_firstname_set)
} else { } else {
if firstNameSet { if firstNameSet {
@ -746,10 +697,6 @@ func (h *MenuHandlers) SaveFamilyname(ctx context.Context, sym string, input []b
if allowUpdate { if allowUpdate {
temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryFamilyName, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryFamilyName) == 0 {
logg.ErrorCtxf(ctx, "temporaryFamilyName is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME, []byte(temporaryFamilyName)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME, []byte(temporaryFamilyName))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write familyName entry with", "key", storedb.DATA_FAMILY_NAME, "value", temporaryFamilyName, "error", err) logg.ErrorCtxf(ctx, "failed to write familyName entry with", "key", storedb.DATA_FAMILY_NAME, "value", temporaryFamilyName, "error", err)
@ -820,10 +767,6 @@ func (h *MenuHandlers) SaveYob(ctx context.Context, sym string, input []byte) (r
if allowUpdate { if allowUpdate {
temporaryYob, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryYob, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryYob) == 0 {
logg.ErrorCtxf(ctx, "temporaryYob is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_YOB, []byte(temporaryYob)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_YOB, []byte(temporaryYob))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write yob entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", temporaryYob, "error", err) logg.ErrorCtxf(ctx, "failed to write yob entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", temporaryYob, "error", err)
@ -863,10 +806,6 @@ func (h *MenuHandlers) SaveLocation(ctx context.Context, sym string, input []byt
if allowUpdate { if allowUpdate {
temporaryLocation, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryLocation, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryLocation) == 0 {
logg.ErrorCtxf(ctx, "temporaryLocation is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_LOCATION, []byte(temporaryLocation)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_LOCATION, []byte(temporaryLocation))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write location entry with", "key", storedb.DATA_LOCATION, "value", temporaryLocation, "error", err) logg.ErrorCtxf(ctx, "failed to write location entry with", "key", storedb.DATA_LOCATION, "value", temporaryLocation, "error", err)
@ -908,10 +847,6 @@ func (h *MenuHandlers) SaveGender(ctx context.Context, sym string, input []byte)
if allowUpdate { if allowUpdate {
temporaryGender, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryGender, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryGender) == 0 {
logg.ErrorCtxf(ctx, "temporaryGender is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_GENDER, []byte(temporaryGender)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_GENDER, []byte(temporaryGender))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write gender entry with", "key", storedb.DATA_GENDER, "value", gender, "error", err) logg.ErrorCtxf(ctx, "failed to write gender entry with", "key", storedb.DATA_GENDER, "value", gender, "error", err)
@ -953,10 +888,6 @@ func (h *MenuHandlers) SaveOfferings(ctx context.Context, sym string, input []by
if allowUpdate { if allowUpdate {
temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) temporaryOfferings, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(temporaryOfferings) == 0 {
logg.ErrorCtxf(ctx, "temporaryOfferings is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
err = store.WriteEntry(ctx, sessionId, storedb.DATA_OFFERINGS, []byte(temporaryOfferings)) err = store.WriteEntry(ctx, sessionId, storedb.DATA_OFFERINGS, []byte(temporaryOfferings))
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "failed to write offerings entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", offerings, "error", err) logg.ErrorCtxf(ctx, "failed to write offerings entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", offerings, "error", err)
@ -1145,11 +1076,6 @@ func (h *MenuHandlers) GetProfileInfo(ctx context.Context, sym string, input []b
gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_GENDER)) gender := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_GENDER))
location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_LOCATION)) location := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_LOCATION))
offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_OFFERINGS)) offerings := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_OFFERINGS))
alias := getEntryOrDefault(store.ReadEntry(ctx, sessionId, storedb.DATA_ACCOUNT_ALIAS))
if alias != defaultValue {
alias = strings.Split(alias, ".")[0]
}
// Construct the full name // Construct the full name
name := person.ConstructName(firstName, familyName, defaultValue) name := person.ConstructName(firstName, familyName, defaultValue)
@ -1166,18 +1092,18 @@ func (h *MenuHandlers) GetProfileInfo(ctx context.Context, sym string, input []b
switch language.Code { switch language.Code {
case "eng": case "eng":
res.Content = fmt.Sprintf( res.Content = fmt.Sprintf(
"Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\nYour alias: %s\n", "Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\n",
name, gender, age, location, offerings, alias, name, gender, age, location, offerings,
) )
case "swa": case "swa":
res.Content = fmt.Sprintf( res.Content = fmt.Sprintf(
"Jina: %s\nJinsia: %s\nUmri: %s\nEneo: %s\nUnauza: %s\nLakabu yako: %s\n", "Jina: %s\nJinsia: %s\nUmri: %s\nEneo: %s\nUnauza: %s\n",
name, gender, age, location, offerings, alias, name, gender, age, location, offerings,
) )
default: default:
res.Content = fmt.Sprintf( res.Content = fmt.Sprintf(
"Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\nYour alias: %s\n", "Name: %s\nGender: %s\nAge: %s\nLocation: %s\nYou provide: %s\n",
name, gender, age, location, offerings, alias, name, gender, age, location, offerings,
) )
} }
@ -1233,10 +1159,6 @@ func (h *MenuHandlers) UpdateAllProfileItems(ctx context.Context, sym string, in
if err != nil { if err != nil {
return res, err return res, err
} }
err = h.constructAccountAlias(ctx)
if err != nil {
return res, err
}
return res, nil return res, nil
} }
@ -1282,9 +1204,7 @@ func (h *MenuHandlers) Authorize(ctx context.Context, sym string, input []byte)
logg.ErrorCtxf(ctx, "failed to read AccountPin entry with", "key", storedb.DATA_ACCOUNT_PIN, "error", err) logg.ErrorCtxf(ctx, "failed to read AccountPin entry with", "key", storedb.DATA_ACCOUNT_PIN, "error", err)
return res, err return res, err
} }
str := string(input) if len(input) == 4 {
_, err = strconv.Atoi(str)
if len(input) == 4 && err == nil {
if pin.VerifyPIN(string(AccountPin), string(input)) { if pin.VerifyPIN(string(AccountPin), string(input)) {
if h.st.MatchFlag(flag_account_authorized, false) { if h.st.MatchFlag(flag_account_authorized, false) {
res.FlagReset = append(res.FlagReset, flag_incorrect_pin) res.FlagReset = append(res.FlagReset, flag_incorrect_pin)
@ -1302,7 +1222,7 @@ func (h *MenuHandlers) Authorize(ctx context.Context, sym string, input []byte)
} }
} }
} else { } else {
err = h.incrementIncorrectPINAttempts(ctx, sessionId) err := h.incrementIncorrectPINAttempts(ctx, sessionId)
if err != nil { if err != nil {
return res, err return res, err
} }
@ -1319,13 +1239,11 @@ func (h *MenuHandlers) Authorize(ctx context.Context, sym string, input []byte)
// Setback sets the flag_back_set flag when the navigation is back. // Setback sets the flag_back_set flag when the navigation is back.
func (h *MenuHandlers) SetBack(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) SetBack(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
flag_back_set, _ := h.flagManager.GetFlag("flag_back_set")
//TODO: //TODO:
//Add check if the navigation is lateral nav instead of checking the input. //Add check if the navigation is lateral nav instead of checking the input.
if string(input) == "0" { if string(input) == "0" {
flag_back_set, _ := h.flagManager.GetFlag("flag_back_set")
res.FlagSet = append(res.FlagSet, flag_back_set) res.FlagSet = append(res.FlagSet, flag_back_set)
} else {
res.FlagReset = append(res.FlagReset, flag_back_set)
} }
return res, nil return res, nil
} }
@ -1481,16 +1399,16 @@ func (h *MenuHandlers) FetchCommunityBalance(ctx context.Context, sym string, in
// TODO: split up functino // TODO: split up functino
func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) { func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input []byte) (resource.Result, error) {
var res resource.Result var res resource.Result
var AliasAddressResult string
var AliasAddress *models.AliasAddress
store := h.userdataStore store := h.userdataStore
sessionId, ok := ctx.Value("SessionId").(string) sessionId, ok := ctx.Value("SessionId").(string)
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient") flag_invalid_recipient, _ := h.flagManager.GetFlag("flag_invalid_recipient")
flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite") flag_invalid_recipient_with_invite, _ := h.flagManager.GetFlag("flag_invalid_recipient_with_invite")
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
recipient := string(input) recipient := string(input)
@ -1550,36 +1468,21 @@ func (h *MenuHandlers) ValidateRecipient(ctx context.Context, sym string, input
} }
case "alias": case "alias":
if strings.Contains(recipient, ".") { // Call the API to validate and retrieve the address for the alias
AliasAddress, err = h.accountService.CheckAliasAddress(ctx, recipient) r, aliasErr := h.accountService.CheckAliasAddress(ctx, recipient)
if err == nil { if aliasErr != nil {
AliasAddressResult = AliasAddress.Address res.FlagSet = append(res.FlagSet, flag_api_error)
} else {
logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err)
}
} else {
//Perform a search for each search domain,break on first match
for _, domain := range config.SearchDomains() {
fqdn := fmt.Sprintf("%s.%s", recipient, domain)
AliasAddress, err = h.accountService.CheckAliasAddress(ctx, fqdn)
if err == nil {
AliasAddressResult = AliasAddress.Address
continue
} else {
logg.ErrorCtxf(ctx, "failed to resolve alias", "alias", recipient, "error_alias_check", err)
}
}
}
if AliasAddressResult == "" {
res.Content = recipient res.Content = recipient
res.FlagSet = append(res.FlagSet, flag_invalid_recipient)
return res, nil logg.ErrorCtxf(ctx, "failed on CheckAliasAddress", "error", aliasErr)
} else { return res, err
err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(AliasAddressResult)) }
if err != nil {
logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", AliasAddressResult, "error", err) // Alias validation succeeded, save the Ethereum address
return res, err err = store.WriteEntry(ctx, sessionId, storedb.DATA_RECIPIENT, []byte(r.Address))
} if err != nil {
logg.ErrorCtxf(ctx, "failed to write recipient entry with", "key", storedb.DATA_RECIPIENT, "value", r.Address, "error", err)
return res, err
} }
} }
} }
@ -1631,10 +1534,6 @@ func (h *MenuHandlers) InviteValidRecipient(ctx context.Context, sym string, inp
l.AddDomain("default") l.AddDomain("default")
recipient, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) recipient, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(recipient) == 0 {
logg.ErrorCtxf(ctx, "recipient is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
// TODO // TODO
// send an invitation SMS // send an invitation SMS
@ -1753,10 +1652,6 @@ func (h *MenuHandlers) GetRecipient(ctx context.Context, sym string, input []byt
} }
store := h.userdataStore store := h.userdataStore
recipient, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE) recipient, _ := store.ReadEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE)
if len(recipient) == 0 {
logg.ErrorCtxf(ctx, "recipient is empty", "key", storedb.DATA_TEMPORARY_VALUE)
return res, fmt.Errorf("Data error encountered")
}
res.Content = string(recipient) res.Content = string(recipient)
@ -2120,6 +2015,7 @@ func (h *MenuHandlers) GetVoucherDetails(ctx context.Context, sym string, input
if !ok { if !ok {
return res, fmt.Errorf("missing session") return res, fmt.Errorf("missing session")
} }
flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error") flag_api_error, _ := h.flagManager.GetFlag("flag_api_call_error")
// get the active address // get the active address
@ -2315,7 +2211,6 @@ func (h *MenuHandlers) ViewTransactionStatement(ctx context.Context, sym string,
return res, nil return res, nil
} }
// persistInitialLanguageCode receives an initial language code and persists it to the store
func (h *MenuHandlers) persistInitialLanguageCode(ctx context.Context, sessionId string, code string) error { func (h *MenuHandlers) persistInitialLanguageCode(ctx context.Context, sessionId string, code string) error {
store := h.userdataStore store := h.userdataStore
_, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INITIAL_LANGUAGE_CODE) _, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INITIAL_LANGUAGE_CODE)
@ -2347,68 +2242,3 @@ func (h *MenuHandlers) persistLanguageCode(ctx context.Context, code string) err
} }
return h.persistInitialLanguageCode(ctx, sessionId, code) return h.persistInitialLanguageCode(ctx, sessionId, code)
} }
// constructAccountAlias retrieves and alias based on the first and family name
// and writes the result in DATA_ACCOUNT_ALIAS
func (h *MenuHandlers) constructAccountAlias(ctx context.Context) error {
var alias string
store := h.userdataStore
sessionId, ok := ctx.Value("SessionId").(string)
if !ok {
return fmt.Errorf("missing session")
}
firstName, err := store.ReadEntry(ctx, sessionId, storedb.DATA_FIRST_NAME)
if err != nil {
if db.IsNotFound(err) {
return nil
}
return err
}
familyName, err := store.ReadEntry(ctx, sessionId, storedb.DATA_FAMILY_NAME)
if err != nil {
if db.IsNotFound(err) {
return nil
}
return err
}
pubKey, err := store.ReadEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY)
if err != nil {
if db.IsNotFound(err) {
return nil
}
return err
}
aliasInput := fmt.Sprintf("%s%s", firstName, familyName)
aliasResult, err := h.accountService.RequestAlias(ctx, string(pubKey), aliasInput)
if err != nil {
logg.ErrorCtxf(ctx, "failed to retrieve alias", "alias", aliasInput, "error_alias_request", err)
return fmt.Errorf("Failed to retrieve alias: %s", err.Error())
}
alias = aliasResult.Alias
//Store the alias
err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACCOUNT_ALIAS, []byte(alias))
if err != nil {
logg.ErrorCtxf(ctx, "failed to write account alias", "key", storedb.DATA_ACCOUNT_ALIAS, "value", alias, "error", err)
return err
}
return nil
}
// ClearTemporaryValue empties the DATA_TEMPORARY_VALUE at the main menu to prevent
// previously stored data from being accessed
func (h *MenuHandlers) ClearTemporaryValue(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")
}
userStore := h.userdataStore
// clear the temporary value at the start
err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(""))
if err != nil {
logg.ErrorCtxf(ctx, "failed to clear DATA_TEMPORARY_VALUE entry with", "key", storedb.DATA_TEMPORARY_VALUE, "value", "empty", "error", err)
return res, err
}
return res, nil
}

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,13 @@ func (eu *EventsUpdater) HandleCustodialRegistration(ctx context.Context, ev *ap
if err != nil { if err != nil {
return err return err
} }
// 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) logg.DebugCtxf(ctx, "received custodial registration event", "identity", identity)
return nil return nil
} }

View File

@ -4,12 +4,12 @@ import (
"context" "context"
"fmt" "fmt"
"git.defalsify.org/vise.git/logging"
"git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/persist"
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event" "git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
) )
var ( var (
@ -17,9 +17,9 @@ var (
) )
type EventsUpdater struct { type EventsUpdater struct {
api remote.AccountService api remote.AccountService
formatFunc func(string, int, any) string formatFunc func(string, int, any) string
store storage.StorageService store storage.StorageService
} }
func NewEventsUpdater(api remote.AccountService, store storage.StorageService) *EventsUpdater { func NewEventsUpdater(api remote.AccountService, store storage.StorageService) *EventsUpdater {

View File

@ -6,13 +6,13 @@ import (
"strings" "strings"
"git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/db"
"git.grassecon.net/grassrootseconomics/common/identity"
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
"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/common/identity"
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
) )
// execute all // execute all
func (eu *EventsUpdater) updateToken(ctx context.Context, identity identity.Identity, userStore *store.UserDataStore, tokenAddress string) error { func (eu *EventsUpdater) updateToken(ctx context.Context, identity identity.Identity, userStore *store.UserDataStore, tokenAddress string) error {
err := eu.updateTokenList(ctx, identity, userStore) err := eu.updateTokenList(ctx, identity, userStore)
if err != nil { if err != nil {
@ -47,6 +47,7 @@ func (eu *EventsUpdater) updateToken(ctx context.Context, identity identity.Iden
return nil return nil
} }
// set default token to given symbol. // set default token to given symbol.
func (eu *EventsUpdater) updateDefaultToken(ctx context.Context, identity identity.Identity, userStore *store.UserDataStore, activeSym string) error { func (eu *EventsUpdater) updateDefaultToken(ctx context.Context, identity identity.Identity, userStore *store.UserDataStore, activeSym string) error {
pfxDb := toPrefixDb(userStore, identity.SessionId) pfxDb := toPrefixDb(userStore, identity.SessionId)
@ -58,6 +59,7 @@ func (eu *EventsUpdater) updateDefaultToken(ctx context.Context, identity identi
return store.UpdateVoucherData(ctx, userStore, identity.SessionId, tokenData) return store.UpdateVoucherData(ctx, userStore, identity.SessionId, tokenData)
} }
// handle token transfer. // handle token transfer.
// //
// if from and to are NOT the same, handle code will be executed once for each side of the transfer. // if from and to are NOT the same, handle code will be executed once for each side of the transfer.
@ -187,7 +189,7 @@ func (eu *EventsUpdater) updateTokenTransferList(ctx context.Context, identity i
return err return err
} }
for i, tx := range txs { for i, tx := range(txs) {
r = append(r, eu.formatFunc(apievent.EventTokenTransferTag, i, tx)) r = append(r, eu.formatFunc(apievent.EventTokenTransferTag, i, tx))
} }

View File

@ -6,7 +6,6 @@ import (
"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/logging"
"git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/persist"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
@ -14,10 +13,6 @@ import (
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
) )
var (
logg = logging.NewVanilla().WithDomain("sarafu-vise.engine")
)
type HandlerService interface { type HandlerService interface {
GetHandler() (*application.MenuHandlers, error) GetHandler() (*application.MenuHandlers, error)
} }
@ -29,7 +24,6 @@ type LocalHandlerService struct {
UserdataStore *db.Db UserdataStore *db.Db
Cfg engine.Config Cfg engine.Config
Rs resource.Resource Rs resource.Resource
first resource.EntryFunc
} }
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) {
@ -66,6 +60,7 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService)
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("check_blocked_status", appHandlers.CheckBlockedStatus) ls.DbRs.AddLocalFunc("check_blocked_status", appHandlers.CheckBlockedStatus)
ls.DbRs.AddLocalFunc("set_language", appHandlers.SetLanguage) ls.DbRs.AddLocalFunc("set_language", appHandlers.SetLanguage)
@ -123,20 +118,13 @@ func (ls *LocalHandlerService) GetHandler(accountService remote.AccountService)
ls.DbRs.AddLocalFunc("update_all_profile_items", appHandlers.UpdateAllProfileItems) ls.DbRs.AddLocalFunc("update_all_profile_items", appHandlers.UpdateAllProfileItems)
ls.DbRs.AddLocalFunc("set_back", appHandlers.SetBack) ls.DbRs.AddLocalFunc("set_back", appHandlers.SetBack)
ls.DbRs.AddLocalFunc("show_blocked_account", appHandlers.ShowBlockedAccount) ls.DbRs.AddLocalFunc("show_blocked_account", appHandlers.ShowBlockedAccount)
ls.DbRs.AddLocalFunc("clear_temporary_value", appHandlers.ClearTemporaryValue)
ls.first = appHandlers.Init
return appHandlers, nil return appHandlers, nil
} }
func (ls *LocalHandlerService) GetEngine(cfg engine.Config, rs resource.Resource, pr *persist.Persister) engine.Engine { // TODO: enable setting of sessionId on engine init time
en := engine.NewEngine(cfg, rs) func (ls *LocalHandlerService) GetEngine() *engine.DefaultEngine {
if ls.first != nil { en := engine.NewEngine(ls.Cfg, ls.Rs)
en = en.WithFirst(ls.first) en = en.WithPersister(ls.Pe)
}
en = en.WithPersister(pr)
if cfg.EngineDebug {
en = en.WithDebug(nil)
}
return en return en
} }

View File

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application"
) )
var ( var (
@ -14,17 +14,17 @@ var (
) )
type Cmd struct { type Cmd struct {
sessionId string sessionId string
conn storage.ConnData conn storage.ConnData
flagParser *application.FlagManager flagParser *application.FlagManager
cmd int cmd int
enable bool enable bool
exec func(ctx context.Context, ss storage.StorageService) error exec func(ctx context.Context, ss storage.StorageService) error
} }
func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd { func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd {
return &Cmd{ return &Cmd{
sessionId: sessionId, sessionId: sessionId,
flagParser: flagParser, flagParser: flagParser,
} }
} }
@ -94,3 +94,5 @@ func (c *Cmd) Parse(args []string) error {
return fmt.Errorf("unknown subcommand: %s", cmd) return fmt.Errorf("unknown subcommand: %s", cmd)
} }

View File

@ -1,67 +1,5 @@
{ {
"groups": [ "groups": [
{
"name": "main_my_vouchers_select_voucher_using_index",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "2",
"expectedContent": "My vouchers\n1:Select voucher\n2:Voucher details\n0:Back"
},
{
"input": "1",
"expectedContent": "Select number or symbol from your vouchers:\n1SRF\n0:Back\n99:Quit"
},
{
"input": "",
"expectedContent": "Select number or symbol from your vouchers:\n1SRF\n0:Back\n99:Quit"
},
{
"input": "1",
"expectedContent": "Enter PIN to confirm selection:\nSymbol: SRF\nBalance: 2.745987\n0:Back\n9:Quit"
},
{
"input": "1234",
"expectedContent": "Success! SRF is now your active voucher.\n0:Back\n9:Quit"
},
{
"input": "0",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
}
]
},
{
"name": "main_my_vouchers_select_voucher_using_symbol",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "2",
"expectedContent": "My vouchers\n1:Select voucher\n2:Voucher details\n0:Back"
},
{
"input": "1",
"expectedContent": "Select number or symbol from your vouchers:\n1SRF\n0:Back\n99:Quit"
},
{
"input": "SRF",
"expectedContent": "Enter PIN to confirm selection:\nSymbol: SRF\nBalance: 2.745987\n0:Back\n9:Quit"
},
{
"input": "1234",
"expectedContent": "Success! SRF is now your active voucher.\n0:Back\n9:Quit"
},
{
"input": "0",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
}
]
},
{ {
"name": "my_account_change_pin", "name": "my_account_change_pin",
"steps": [ "steps": [
@ -110,17 +48,13 @@
"input": "3", "input": "3",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
}, },
{
"input": "",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{ {
"input": "2", "input": "2",
"expectedContent": "Please enter your PIN:" "expectedContent": "Please enter your PIN:"
}, },
{ {
"input": "1235", "input": "1235",
"expectedContent": "Incorrect PIN. You have: {attempts} remaining attempt(s).\n1:Retry\n9:Quit" "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit"
}, },
{ {
"input": "1", "input": "1",
@ -140,121 +74,6 @@
} }
] ]
}, },
{
"name": "menu_my_account_reset_others_pin_with_unregistered_number",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "3",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{
"input": "5",
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back"
},
{
"input": "2",
"expectedContent": "Enter other's phone number:\n0:Back"
},
{
"input": "0700000001",
"expectedContent": "The number you have entered is either not registered with Sarafu or is invalid.\n1:Retry\n9:Quit"
},
{
"input": "1",
"expectedContent": "Enter other's phone number:\n0:Back"
},
{
"input": "0",
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back"
},
{
"input": "0",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{
"input": "0",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
}
]
},
{
"name": "menu_my_account_reset_others_pin_with_registered_number",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "3",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{
"input": "5",
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back"
},
{
"input": "2",
"expectedContent": "Enter other's phone number:\n0:Back"
},
{
"input": "0700000000",
"expectedContent": "Please enter new PIN for: {secondary_session_id}\n0:Back"
},
{
"input": "11111",
"expectedContent": "The PIN you have entered is invalid.Please try a 4 digit number instead.\n1:Retry\n9:Quit"
},
{
"input": "1",
"expectedContent": "Please enter new PIN for: {secondary_session_id}\n0:Back"
},
{
"input": "1111",
"expectedContent": "Please confirm new PIN for: {secondary_session_id}\n0:Back"
},
{
"input": "1111",
"expectedContent": "Please enter your PIN:"
},
{
"input": "1234",
"expectedContent": "PIN reset request for {secondary_session_id} was successful\n0:Back\n9:Quit"
},
{
"input": "0",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
}
]
},
{
"name": "menu_my_account_reset_others_pin_with_no_privileges",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "3",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{
"input": "5",
"expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n0:Back"
},
{
"input": "2",
"expectedContent": "You do not have privileges to perform this action\n\n9:Quit\n0:Back"
},
{
"input": "0",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
}
]
},
{ {
"name": "menu_my_account_check_my_balance", "name": "menu_my_account_check_my_balance",
"steps": [ "steps": [
@ -276,7 +95,7 @@
}, },
{ {
"input": "1235", "input": "1235",
"expectedContent": "Incorrect PIN. You have: {attempts} remaining attempt(s).\n1:Retry\n9:Quit" "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit"
}, },
{ {
"input": "1", "input": "1",
@ -321,7 +140,7 @@
}, },
{ {
"input": "1235", "input": "1235",
"expectedContent": "Incorrect PIN. You have: {attempts} remaining attempt(s).\n1:Retry\n9:Quit" "expectedContent": "Incorrect PIN. You have: 2 remaining attempt(s).\n1:Retry\n9:Quit"
}, },
{ {
"input": "1", "input": "1",
@ -458,10 +277,6 @@
"input": "3", "input": "3",
"expectedContent": "Select gender: \n1:Male\n2:Female\n3:Unspecified\n0:Back" "expectedContent": "Select gender: \n1:Male\n2:Female\n3:Unspecified\n0:Back"
}, },
{
"input": "",
"expectedContent": "Select gender: \n1:Male\n2:Female\n3:Unspecified\n0:Back"
},
{ {
"input": "1", "input": "1",
"expectedContent": "Please enter your PIN:" "expectedContent": "Please enter your PIN:"
@ -612,7 +427,7 @@
}, },
{ {
"input": "1234", "input": "1234",
"expectedContent": "My profile:\nName: foo bar\nGender: male\nAge: 80\nLocation: Kilifi\nYou provide: Bananas\nYour alias: \n\n0:Back\n9:Quit" "expectedContent": "My profile:\nName: foo bar\nGender: male\nAge: 80\nLocation: Kilifi\nYou provide: Bananas\n\n0:Back\n9:Quit"
}, },
{ {
"input": "0", "input": "0",
@ -623,47 +438,6 @@
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" "expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
} }
] ]
},
{
"name": "menu_block_account_via_view_profile",
"steps": [
{
"input": "",
"expectedContent": "{balance}\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit"
},
{
"input": "3",
"expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back"
},
{
"input": "1",
"expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back"
},
{
"input": "7",
"expectedContent": "Please enter your PIN:"
},
{
"input": "1254",
"expectedContent": "Incorrect PIN. You have: {attempts} remaining attempt(s).\n1:Retry\n9:Quit"
},
{
"input": "1",
"expectedContent": "Please enter your PIN:"
},
{
"input": "1254",
"expectedContent": "Incorrect PIN. You have: {attempts} remaining attempt(s).\n1:Retry\n9:Quit"
},
{
"input": "1",
"expectedContent": "Please enter your PIN:"
},
{
"input": "1254",
"expectedContent": "Your account has been locked. For help on how to unblock your account, contact support at: 0757628885"
}
]
} }
] ]
} }

View File

@ -9,19 +9,18 @@ import (
"regexp" "regexp"
"testing" "testing"
"git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/testutil"
"git.grassecon.net/grassrootseconomics/visedriver/testutil/driver"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/visedriver/testutil/driver"
"git.grassecon.net/grassrootseconomics/sarafu-vise/testutil"
) )
var ( var (
logg = logging.NewVanilla().WithDomain("menutraversaltest") logg = logging.NewVanilla().WithDomain("menutraversaltest")
testData = driver.ReadData() testData = driver.ReadData()
sessionID string sessionID string
src = rand.NewSource(42) src = rand.NewSource(42)
g = rand.New(src) g = rand.New(src)
secondarySessionId = "+254700000000"
) )
var groupTestFile = flag.String("test-file", "group_test.json", "The test file to use for running the group tests") var groupTestFile = flag.String("test-file", "group_test.json", "The test file to use for running the group tests")
@ -68,16 +67,6 @@ func extractMaxAmount(response []byte) string {
return "" return ""
} }
func extractRemainingAttempts(response []byte) string {
// Regex to match "You have: <number> remaining attempt(s)"
re := regexp.MustCompile(`(?m)You have:\s+(\d+)\s+remaining attempt\(s\)`)
match := re.FindSubmatch(response)
if match != nil {
return string(match[1]) // "<number>" of remaining attempts
}
return ""
}
// Extracts the send amount value from the engine response. // Extracts the send amount value from the engine response.
func extractSendAmount(response []byte) string { func extractSendAmount(response []byte) string {
// Regex to match the pattern "will receive X.XX SYM from" // Regex to match the pattern "will receive X.XX SYM from"
@ -98,43 +87,7 @@ func TestMain(m *testing.M) {
} }
func TestAccountCreationSuccessful(t *testing.T) { func TestAccountCreationSuccessful(t *testing.T) {
en, fn, eventChannel, _, _ := testutil.TestEngine(sessionID) en, fn, eventChannel := testutil.TestEngine(sessionID)
defer fn()
ctx := context.Background()
sessions := testData
for _, session := range sessions {
groups := driver.FilterGroupsByName(session.Groups, "account_creation_successful")
for _, group := range groups {
for i, step := range group.Steps {
logg.TraceCtxf(ctx, "executing step", "i", i, "step", step)
cont, err := en.Exec(ctx, []byte(step.Input))
if err != nil {
t.Fatalf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err)
}
if !cont {
break
}
w := bytes.NewBuffer(nil)
_, err = en.Flush(ctx, w)
if err != nil {
t.Fatalf("Test case '%s' failed during Flush: %v", group.Name, err)
}
b := w.Bytes()
match, err := step.MatchesExpectedContent(b)
if err != nil {
t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err)
}
if !match {
t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", step.ExpectedContent, b)
}
}
}
}
<-eventChannel
}
func TestSecondaryAccount(t *testing.T) {
en, fn, eventChannel, _, _ := testutil.TestEngine(secondarySessionId)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -177,7 +130,7 @@ func TestAccountRegistrationRejectTerms(t *testing.T) {
t.Fail() t.Fail()
} }
edgeCaseSessionID := v.String() edgeCaseSessionID := v.String()
en, fn, _, _, _ := testutil.TestEngine(edgeCaseSessionID) en, fn, _ := testutil.TestEngine(edgeCaseSessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -213,7 +166,7 @@ func TestAccountRegistrationRejectTerms(t *testing.T) {
} }
func TestMainMenuHelp(t *testing.T) { func TestMainMenuHelp(t *testing.T) {
en, fn, _, _, _ := testutil.TestEngine(sessionID) en, fn, _ := testutil.TestEngine(sessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -255,7 +208,7 @@ func TestMainMenuHelp(t *testing.T) {
} }
func TestMainMenuQuit(t *testing.T) { func TestMainMenuQuit(t *testing.T) {
en, fn, _, _, _ := testutil.TestEngine(sessionID) en, fn, _ := testutil.TestEngine(sessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -296,7 +249,7 @@ func TestMainMenuQuit(t *testing.T) {
} }
func TestMyAccount_MyAddress(t *testing.T) { func TestMyAccount_MyAddress(t *testing.T) {
en, fn, _, _, _ := testutil.TestEngine(sessionID) en, fn, _ := testutil.TestEngine(sessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -340,7 +293,7 @@ func TestMyAccount_MyAddress(t *testing.T) {
} }
func TestMainMenuSend(t *testing.T) { func TestMainMenuSend(t *testing.T) {
en, fn, _, _, _ := testutil.TestEngine(sessionID) en, fn, _ := testutil.TestEngine(sessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
sessions := testData sessions := testData
@ -391,12 +344,9 @@ func TestGroups(t *testing.T) {
if err != nil { if err != nil {
log.Fatalf("Failed to load test groups: %v", err) log.Fatalf("Failed to load test groups: %v", err)
} }
en, fn, _, pe, flagParser := testutil.TestEngine(sessionID) en, fn, _ := testutil.TestEngine(sessionID)
defer fn() defer fn()
ctx := context.Background() ctx := context.Background()
flag_admin_privilege, _ := flagParser.GetFlag("flag_admin_privilege")
// Create test cases from loaded groups // Create test cases from loaded groups
tests := driver.CreateTestCases(groups) tests := driver.CreateTestCases(groups)
for _, tt := range tests { for _, tt := range tests {
@ -415,21 +365,9 @@ func TestGroups(t *testing.T) {
} }
b := w.Bytes() b := w.Bytes()
balance := extractBalance(b) balance := extractBalance(b)
attempts := extractRemainingAttempts(b)
st := pe.GetState()
if st != nil {
st.SetFlag(flag_admin_privilege)
if tt.Name == "menu_my_account_reset_others_pin_with_no_privileges" {
st.ResetFlag(flag_admin_privilege)
}
}
expectedContent := []byte(tt.ExpectedContent) expectedContent := []byte(tt.ExpectedContent)
expectedContent = bytes.Replace(expectedContent, []byte("{balance}"), []byte(balance), -1) expectedContent = bytes.Replace(expectedContent, []byte("{balance}"), []byte(balance), -1)
expectedContent = bytes.Replace(expectedContent, []byte("{attempts}"), []byte(attempts), -1)
expectedContent = bytes.Replace(expectedContent, []byte("{secondary_session_id}"), []byte(secondarySessionId), -1)
tt.ExpectedContent = string(expectedContent) tt.ExpectedContent = string(expectedContent)

View File

@ -12,7 +12,7 @@ func (p *Profile) InsertOrShift(index int, value string) {
for len(p.ProfileItems) < index { for len(p.ProfileItems) < index {
p.ProfileItems = append(p.ProfileItems, "0") p.ProfileItems = append(p.ProfileItems, "0")
} }
p.ProfileItems = append(p.ProfileItems, "0") p.ProfileItems = append(p.ProfileItems, "0")
p.ProfileItems[index] = value p.ProfileItems[index] = value
} }
} }

View File

@ -1,42 +0,0 @@
package profile
import (
"testing"
"github.com/alecthomas/assert/v2"
"github.com/stretchr/testify/require"
)
func TestInsertOrShift(t *testing.T) {
tests := []struct {
name string
profile Profile
index int
value string
expected []string
}{
{
name: "Insert within range",
profile: Profile{ProfileItems: []string{"A", "B", "C"}, Max: 5},
index: 1,
value: "X",
expected: []string{"A", "X"},
},
{
name: "Insert beyond range",
profile: Profile{ProfileItems: []string{"A"}, Max: 5},
index: 3,
value: "Y",
expected: []string{"A", "0", "0", "Y"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := tt.profile
p.InsertOrShift(tt.index, tt.value)
require.NotNil(t, p.ProfileItems)
assert.Equal(t, tt.expected, p.ProfileItems)
})
}
}

View File

@ -1,17 +1,16 @@
//go:build !online
// +build !online // +build !online
package services package services
import ( import (
"context"
"fmt" "fmt"
"context"
devremote "git.grassecon.net/grassrootseconomics/sarafu-api/dev"
apievent "git.grassecon.net/grassrootseconomics/sarafu-api/event"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/event"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "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 { type localEmitter struct {

View File

@ -1 +1 @@
Please confirm new PIN for: {{.retrieve_blocked_number}} Please confirm new PIN for:{{.retrieve_blocked_number}}

View File

@ -1,4 +1,4 @@
CATCH incorrect_pin flag_incorrect_pin 1 CATCH pin_entry flag_incorrect_pin 1
RELOAD retrieve_blocked_number RELOAD retrieve_blocked_number
MAP retrieve_blocked_number MAP retrieve_blocked_number
CATCH invalid_others_pin flag_valid_pin 0 CATCH invalid_others_pin flag_valid_pin 0
@ -8,7 +8,7 @@ RELOAD save_others_temporary_pin
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP _ 0
LOAD check_pin_mismatch 6 LOAD check_pin_mismatch 0
RELOAD check_pin_mismatch RELOAD check_pin_mismatch
CATCH others_pin_mismatch flag_pin_mismatch 1 CATCH others_pin_mismatch flag_pin_mismatch 1
INCMP pin_entry * INCMP pin_entry *

View File

@ -1,7 +1,5 @@
LOAD confirm_pin_change 0 CATCH invalid_pin flag_valid_pin 0
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP _ 0
RELOAD confirm_pin_change
CATCH pin_reset_mismatch flag_pin_mismatch 1
INCMP * pin_reset_success INCMP * pin_reset_success

View File

@ -1,10 +1,7 @@
CATCH no_admin_privilege flag_admin_privilege 0 CATCH no_admin_privilege flag_admin_privilege 0
LOAD reset_account_authorized 0 LOAD reset_account_authorized 0
RELOAD reset_account_authorized RELOAD reset_account_authorized
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP _ 0
LOAD validate_blocked_number 6
RELOAD validate_blocked_number
CATCH unregistered_number flag_unregistered_number 1
INCMP enter_others_new_pin * INCMP enter_others_new_pin *

View File

@ -1,3 +1,6 @@
LOAD validate_blocked_number 6
RELOAD validate_blocked_number
CATCH unregistered_number flag_unregistered_number 1
LOAD retrieve_blocked_number 0 LOAD retrieve_blocked_number 0
RELOAD retrieve_blocked_number RELOAD retrieve_blocked_number
MAP retrieve_blocked_number MAP retrieve_blocked_number

View File

@ -7,4 +7,3 @@ MOUT quit 9
HALT HALT
INCMP _ 1 INCMP _ 1
INCMP quit 9 INCMP quit 9
INCMP . *

View File

@ -1,5 +1,3 @@
LOAD clear_temporary_value 2
RELOAD clear_temporary_value
LOAD set_default_voucher 8 LOAD set_default_voucher 8
RELOAD set_default_voucher RELOAD set_default_voucher
LOAD check_vouchers 10 LOAD check_vouchers 10

View File

@ -1,7 +1,13 @@
LOAD authorize_account 12
RELOAD authorize_account
CATCH incorrect_pin flag_incorrect_pin 1
CATCH old_pin flag_allow_update 0
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP _ 0
LOAD save_temporary_pin 6
LOAD verify_new_pin 0
RELOAD save_temporary_pin RELOAD save_temporary_pin
RELOAD verify_new_pin RELOAD verify_new_pin
CATCH invalid_pin flag_valid_pin 0
INCMP * confirm_pin_change INCMP * confirm_pin_change

View File

@ -1,5 +1,5 @@
MOUT quit 9 MOUT quit 9
MOUT back 0 MOUT back 0
HALT HALT
INCMP ^ 0 INCMP pin_management 0
INCMP quit 9 INCMP quit 9

View File

@ -1,8 +1,7 @@
RELOAD reset_allow_update LOAD reset_allow_update 0
MOUT back 0 MOUT back 0
HALT HALT
RELOAD reset_allow_update
INCMP _ 0 INCMP _ 0
RELOAD authorize_account
CATCH incorrect_pin flag_incorrect_pin 1
CATCH _ flag_allow_update 0
INCMP new_pin * INCMP new_pin *

View File

@ -3,4 +3,3 @@ MOUT quit 9
HALT HALT
INCMP _ 1 INCMP _ 1
INCMP quit 9 INCMP quit 9
INCMP . *

View File

@ -1,14 +1,8 @@
LOAD set_back 6
LOAD authorize_account 5
LOAD reset_allow_update 4
LOAD verify_new_pin 2
LOAD save_temporary_pin 1
LOAD reset_incorrect 0
MOUT change_pin 1 MOUT change_pin 1
MOUT reset_pin 2 MOUT reset_pin 2
MOUT back 0 MOUT back 0
HALT HALT
INCMP _ 0 INCMP my_account 0
INCMP old_pin 1 INCMP old_pin 1
INCMP enter_other_number 2 INCMP enter_other_number 2
INCMP . * INCMP . *

View File

@ -1,6 +1,6 @@
MOUT retry 1 MOUT retry 1
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP _ 1 INCMP confirm_pin_change 1
INCMP quit 9 INCMP quit 9
INCMP . *

View File

@ -4,5 +4,5 @@ LOAD reset_others_pin 6
MOUT back 0 MOUT back 0
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP ^ 0 INCMP pin_management 0
INCMP quit 9 INCMP quit 9

View File

@ -1,6 +1,8 @@
LOAD confirm_pin_change 0
RELOAD confirm_pin_change
CATCH pin_reset_mismatch flag_pin_mismatch 1
MOUT back 0 MOUT back 0
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP main 0 INCMP main 0
INCMP quit 9 INCMP quit 9
INCMP . *

View File

@ -1,8 +1,7 @@
LOAD reset_unregistered_number 0 LOAD reset_unregistered_number 0
RELOAD reset_unregistered_number RELOAD reset_unregistered_number
MOUT retry 1 MOUT back 0
MOUT quit 9 MOUT quit 9
HALT HALT
INCMP _ 1 INCMP ^ 0
INCMP quit 9 INCMP quit 9
INCMP . *

View File

@ -1,4 +1,3 @@
//go:build online
// +build online // +build online
package services package services
@ -6,14 +5,11 @@ package services
import ( import (
"context" "context"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote" "git.grassecon.net/grassrootseconomics/sarafu-api/remote"
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http" httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
) )
func New(ctx context.Context, storageService storage.StorageService) remote.AccountService { func New(ctx context.Context, storageService storage.StorageService, conn storage.ConnData) remote.AccountService {
return &httpremote.HTTPAccountService{ return &httpremote.HTTPAccountService{}
SS: storageService,
UseApi: false,
}
} }

View File

@ -29,7 +29,7 @@ func NewSshKeyStore(ctx context.Context, dbDir string) (*SshKeyStore, error) {
return keyStore, nil return keyStore, nil
} }
func (s *SshKeyStore) AddFromFile(ctx context.Context, fp string, sessionId string) error { func(s *SshKeyStore) AddFromFile(ctx context.Context, fp string, sessionId string) error {
_, err := os.Stat(fp) _, err := os.Stat(fp)
if err != nil { if err != nil {
return fmt.Errorf("cannot open ssh server public key file: %v\n", err) return fmt.Errorf("cannot open ssh server public key file: %v\n", err)
@ -51,7 +51,7 @@ func (s *SshKeyStore) AddFromFile(ctx context.Context, fp string, sessionId stri
return s.store.Put(ctx, k, []byte(sessionId)) return s.store.Put(ctx, k, []byte(sessionId))
} }
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.SetSession("")
s.store.SetPrefix(storage.DATATYPE_EXTEND) s.store.SetPrefix(storage.DATATYPE_EXTEND)
@ -63,6 +63,6 @@ func (s *SshKeyStore) Get(ctx context.Context, pubKey ssh.PublicKey) (string, er
return string(v), nil return string(v), nil
} }
func (s *SshKeyStore) Close(ctx context.Context) error { func(s *SshKeyStore) Close(ctx context.Context) error {
return s.store.Close(ctx) return s.store.Close(ctx)
} }

View File

@ -2,8 +2,8 @@ package ssh
import ( import (
"context" "context"
"encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"net" "net"
@ -16,9 +16,9 @@ import (
"git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/logging"
"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-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/services"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
) )
var ( var (
@ -26,32 +26,32 @@ var (
) )
type auther struct { type auther struct {
Ctx context.Context Ctx context.Context
keyStore *SshKeyStore keyStore *SshKeyStore
auth map[string]string auth map[string]string
} }
func NewAuther(ctx context.Context, keyStore *SshKeyStore) *auther { func NewAuther(ctx context.Context, keyStore *SshKeyStore) *auther {
return &auther{ return &auther{
Ctx: ctx, Ctx: ctx,
keyStore: keyStore, keyStore: keyStore,
auth: make(map[string]string), auth: make(map[string]string),
} }
} }
func (a *auther) Check(conn ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { func(a *auther) Check(conn ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
logg.TraceCtxf(a.Ctx, "looking for publickey", "pubkey", fmt.Sprintf("%x", pubKey)) logg.TraceCtxf(a.Ctx, "looking for publickey", "pubkey", fmt.Sprintf("%x", pubKey))
va, err := a.keyStore.Get(a.Ctx, pubKey) va, err := a.keyStore.Get(a.Ctx, pubKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ka := hex.EncodeToString(conn.SessionID()) ka := hex.EncodeToString(conn.SessionID())
a.auth[ka] = va a.auth[ka] = va
fmt.Fprintf(os.Stderr, "connect: %s -> %s\n", ka, va) fmt.Fprintf(os.Stderr, "connect: %s -> %s\n", ka, va)
return nil, nil return nil, nil
} }
func (a *auther) FromConn(c *ssh.ServerConn) (string, error) { func(a *auther) FromConn(c *ssh.ServerConn) (string, error) {
if c == nil { if c == nil {
return "", errors.New("nil server conn") return "", errors.New("nil server conn")
} }
@ -61,7 +61,8 @@ func (a *auther) FromConn(c *ssh.ServerConn) (string, error) {
return a.Get(c.Conn.SessionID()) return a.Get(c.Conn.SessionID())
} }
func (a *auther) Get(k []byte) (string, error) {
func(a *auther) Get(k []byte) (string, error) {
ka := hex.EncodeToString(k) ka := hex.EncodeToString(k)
v, ok := a.auth[ka] v, ok := a.auth[ka]
if !ok { if !ok {
@ -71,19 +72,19 @@ func (a *auther) Get(k []byte) (string, error) {
} }
type SshRunner struct { type SshRunner struct {
Ctx context.Context Ctx context.Context
Cfg engine.Config Cfg engine.Config
FlagFile string FlagFile string
Conn storage.Conns Conn storage.Conns
Debug bool Debug bool
SrvKeyFile string SrvKeyFile string
Host string Host string
Port uint Port uint
wg sync.WaitGroup wg sync.WaitGroup
lst net.Listener lst net.Listener
} }
func (s *SshRunner) serve(ctx context.Context, sessionId string, ch ssh.NewChannel, en engine.Engine) error { func(s *SshRunner) serve(ctx context.Context, sessionId string, ch ssh.NewChannel, en engine.Engine) error {
if ch == nil { if ch == nil {
return errors.New("nil channel") return errors.New("nil channel")
} }
@ -100,7 +101,7 @@ func (s *SshRunner) serve(ctx context.Context, sessionId string, ch ssh.NewChann
go func(reqIn <-chan *ssh.Request) { go func(reqIn <-chan *ssh.Request) {
defer s.wg.Done() defer s.wg.Done()
for req := range reqIn { for req := range reqIn {
req.Reply(req.Type == "shell", nil) req.Reply(req.Type == "shell", nil)
} }
_ = requests _ = requests
}(requests) }(requests)
@ -140,11 +141,11 @@ func (s *SshRunner) serve(ctx context.Context, sessionId string, ch ssh.NewChann
return nil return nil
} }
func (s *SshRunner) Stop() error { func(s *SshRunner) Stop() error {
return s.lst.Close() return s.lst.Close()
} }
func (s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { func(s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) {
ctx := s.Ctx ctx := s.Ctx
menuStorageService := storage.NewMenuStorageService(s.Conn) menuStorageService := storage.NewMenuStorageService(s.Conn)
@ -177,14 +178,20 @@ func (s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) {
return nil, nil, err return nil, nil, err
} }
// TODO: this is getting very hacky! // TODO: clear up why pointer here and by-value other cmds
accountService := services.New(ctx, menuStorageService) accountService := services.New(ctx, menuStorageService)
_, err = lhs.GetHandler(accountService)
hl, err := lhs.GetHandler(accountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err) return nil, nil, err
os.Exit(1)
} }
en := lhs.GetEngine(lhs.Cfg, rs, pe)
en := lhs.GetEngine()
en = en.WithFirst(hl.Init)
if s.Debug {
en = en.WithDebug(nil)
}
// TODO: this is getting very hacky!
closer := func() { closer := func() {
err := menuStorageService.Close(ctx) err := menuStorageService.Close(ctx)
if err != nil { if err != nil {
@ -195,7 +202,7 @@ func (s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) {
} }
// adapted example from crypto/ssh package, NewServerConn doc // adapted example from crypto/ssh package, NewServerConn doc
func (s *SshRunner) Run(ctx context.Context, keyStore *SshKeyStore) { func(s *SshRunner) Run(ctx context.Context, keyStore *SshKeyStore) {
s.Ctx = ctx s.Ctx = ctx
running := true running := true
@ -248,7 +255,7 @@ func (s *SshRunner) Run(ctx context.Context, keyStore *SshKeyStore) {
ssh.DiscardRequests(rC) ssh.DiscardRequests(rC)
s.wg.Done() s.wg.Done()
}() }()
sessionId, err := auth.FromConn(srvConn) sessionId, err := auth.FromConn(srvConn)
if err != nil { if err != nil {
logg.ErrorCtxf(ctx, "Cannot find authentication") logg.ErrorCtxf(ctx, "Cannot find authentication")

View File

@ -61,8 +61,6 @@ const (
DATA_SELECTED_LANGUAGE_CODE DATA_SELECTED_LANGUAGE_CODE
//ISO 639 code for the language initially selected. //ISO 639 code for the language initially selected.
DATA_INITIAL_LANGUAGE_CODE DATA_INITIAL_LANGUAGE_CODE
//Fully qualified account alias string
DATA_ACCOUNT_ALIAS
) )
const ( const (

View File

@ -3,8 +3,8 @@ package store
import ( import (
"testing" "testing"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"github.com/alecthomas/assert/v2" "github.com/alecthomas/assert/v2"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
) )
func TestParseAndScaleAmount(t *testing.T) { func TestParseAndScaleAmount(t *testing.T) {

View File

@ -4,10 +4,10 @@ import (
"context" "context"
visedb "git.defalsify.org/vise.git/db" visedb "git.defalsify.org/vise.git/db"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
"git.grassecon.net/grassrootseconomics/common/hex" "git.grassecon.net/grassrootseconomics/common/hex"
"git.grassecon.net/grassrootseconomics/common/identity" "git.grassecon.net/grassrootseconomics/common/identity"
"git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db"
) )
// TODO: Rename interface, "datastore" is redundant naming and too general // TODO: Rename interface, "datastore" is redundant naming and too general

View File

@ -9,32 +9,30 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"git.defalsify.org/vise.git/asm" "github.com/jackc/pgx/v5/pgxpool"
"git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/engine"
"git.defalsify.org/vise.git/persist"
"git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/resource"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
"git.grassecon.net/grassrootseconomics/sarafu-api/testutil/testservice"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/sarafu-vise/handlers" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers"
"git.grassecon.net/grassrootseconomics/sarafu-vise/testutil/testtag"
"git.grassecon.net/grassrootseconomics/visedriver/storage" "git.grassecon.net/grassrootseconomics/visedriver/storage"
"github.com/jackc/pgx/v5/pgxpool" "git.grassecon.net/grassrootseconomics/sarafu-api/testutil/testservice"
"git.grassecon.net/grassrootseconomics/sarafu-api/remote"
httpremote "git.grassecon.net/grassrootseconomics/sarafu-api/remote/http"
"git.grassecon.net/grassrootseconomics/sarafu-vise/testutil/testtag"
) )
// CleanDatabase removes all test data from the database // CleanDatabase removes all test data from the database
func CleanDatabase() { func CleanDatabase() {
for _, v := range []int8{ for _, v := range([]int8{
storage.STORETYPE_STATE, storage.STORETYPE_STATE,
storage.STORETYPE_USER, storage.STORETYPE_USER,
} { }) {
conn := conns[v] conn := conns[v]
logg.Infof("cleaning test database", "typ", v, "db", conn) logg.Infof("cleaning test database", "typ", v, "db", conn)
if conn.DbType() == storage.DBTYPE_POSTGRES { if conn.DbType() == storage.DBTYPE_POSTGRES {
ctx := context.Background() ctx := context.Background()
// Update the connection string with the new search path // Update the connection string with the new search path
updatedConnStr := conn.Raw() updatedConnStr := conn.String()
dbConn, err := pgxpool.New(ctx, updatedConnStr) dbConn, err := pgxpool.New(ctx, updatedConnStr)
if err != nil { if err != nil {
@ -62,9 +60,9 @@ func CleanDatabase() {
} }
} }
func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Persister, *asm.FlagParser) { func TestEngine(sessionId string) (engine.Engine, func(), chan bool) {
config.LoadConfig() config.LoadConfig()
err := config.Apply(override) err := config.Apply(&override)
if err != nil { if err != nil {
panic(fmt.Errorf("args override fail: %v\n", err)) panic(fmt.Errorf("args override fail: %v\n", err))
} }
@ -77,12 +75,6 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
logg.InfoCtxf(ctx, "loaded engine setup", "conns", conns) logg.InfoCtxf(ctx, "loaded engine setup", "conns", conns)
pfp := path.Join(scriptDir, "pp.csv") pfp := path.Join(scriptDir, "pp.csv")
parser := asm.NewFlagParser()
_, err = parser.Load(pfp)
if err != nil {
os.Exit(1)
}
var eventChannel = make(chan bool) var eventChannel = make(chan bool)
cfg := engine.Config{ cfg := engine.Config{
@ -145,14 +137,14 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
panic("Unknown account service type") panic("Unknown account service type")
} }
// TODO: triggers withfirst assignment hl, err := lhs.GetHandler(testtag.AccountService)
_, err = lhs.GetHandler(testtag.AccountService)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1) os.Exit(1)
} }
en := lhs.GetEngine(lhs.Cfg, rs, pe) en := lhs.GetEngine()
en = en.WithFirst(hl.Init)
cleanFn := func() { cleanFn := func() {
err := en.Finish(ctx) err := en.Finish(ctx)
if err != nil { if err != nil {
@ -165,5 +157,5 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool, *persist.Pe
} }
logg.Infof("testengine storage closed") logg.Infof("testengine storage closed")
} }
return en, cleanFn, eventChannel, pe, parser return en, cleanFn, eventChannel
} }

View File

@ -5,7 +5,7 @@ import (
) )
func TestCreateEngine(t *testing.T) { func TestCreateEngine(t *testing.T) {
o, clean, eventC, _, _ := TestEngine("foo") o, clean, eventC := TestEngine("foo")
defer clean() defer clean()
defer func() { defer func() {
<-eventC <-eventC

View File

@ -1,25 +1,21 @@
//go:build testfsdb
// +build testfsdb // +build testfsdb
package testutil package testutil
import ( import (
"os" "os"
)
const (
testDbCookie = true
) )
func init() { func init() {
stateDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-fs-state-") stateDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-state-")
if err != nil { if err != nil {
panic(err) panic(err)
} }
override.StateConn = stateDir override.StateConn = &stateDir
userDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-fs-user-") userDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-user-")
if err != nil { if err != nil {
panic(err) panic(err)
} }
override.UserConn = userDir override.UserConn = &userDir
} }

View File

@ -1,34 +0,0 @@
//go:build testgdbmdb
// +build testgdbmdb
package testutil
import (
"net/url"
"os"
)
const (
testDbCookie = true
)
func init() {
stateDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-gdbm-state-")
if err != nil {
panic(err)
}
stateDir, err = url.JoinPath("gdbm:///", stateDir)
if err != nil {
panic(err)
}
override.StateConn = stateDir
userDir, err := os.MkdirTemp("", "sarafu-vise-menutraversal-gdbm-user-")
if err != nil {
panic(err)
}
userDir, err = url.JoinPath("gdbm:///", userDir)
if err != nil {
panic(err)
}
override.UserConn = userDir
}

View File

@ -4,21 +4,21 @@ import (
"context" "context"
"path" "path"
"git.defalsify.org/vise.git/db"
fsdb "git.defalsify.org/vise.git/db/fs"
"git.defalsify.org/vise.git/logging"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
testdataloader "github.com/peteole/testdata-loader" testdataloader "github.com/peteole/testdata-loader"
"git.defalsify.org/vise.git/logging"
fsdb "git.defalsify.org/vise.git/db/fs"
"git.defalsify.org/vise.git/db"
"git.grassecon.net/grassrootseconomics/visedriver/storage"
"git.grassecon.net/grassrootseconomics/sarafu-vise/config"
) )
var ( var (
logg = logging.NewVanilla().WithDomain("sarafu-vise.testutil").WithContextKey("SessionId") logg = logging.NewVanilla().WithDomain("sarafu-vise.testutil").WithContextKey("SessionId")
conns storage.Conns conns storage.Conns
resourceDb db.Db resourceDb db.Db
baseDir = testdataloader.GetBasePath() baseDir = testdataloader.GetBasePath()
scriptDir = path.Join(baseDir, "services", "registration") scriptDir = path.Join(baseDir, "services", "registration")
override = config.NewOverride() override config.Override
) )
func init() { func init() {

View File

@ -1,4 +1,3 @@
//go:build !online
// +build !online // +build !online
package testtag package testtag

View File

@ -1,4 +1,3 @@
//go:build online
// +build online // +build online
package testtag package testtag