diff --git a/config.go b/config.go index 082405f..3d40ac6 100644 --- a/config.go +++ b/config.go @@ -5,3 +5,7 @@ var SCRIPTS = map[string]string{ "register": "r --tail 10", "balance this month": "b -b \"this month\"", } + +const SCRIPTS_FILE = "queries.txt" +const HTPASSWD_FILE = ".htpasswd" +const DEFAULT_JOURNAL = "ledger.txt" diff --git a/main.go b/main.go index 2b7ff7d..23f67d2 100644 --- a/main.go +++ b/main.go @@ -19,9 +19,6 @@ var HOST string var store auth.AuthStore -const HTPASSWD_FILE = ".htpasswd" -const DEFAULT_JOURNAL = "ledger.txt" - func init() { ledgerTpl = template.Must(template.ParseGlob("tx/*")) flag.StringVar(&DATA_DIR, "d", "data", "data folder") diff --git a/models.go b/models.go new file mode 100644 index 0000000..276c8ee --- /dev/null +++ b/models.go @@ -0,0 +1,148 @@ +package main + +import ( + "bufio" + "bytes" + "fmt" + "io" + "log" + "os" + "os/exec" + "path" + "strings" + "time" +) + +type User struct { + IsLogin bool + Email string `form:"email" binding:"required"` + Password string `form:"password" binding:"required"` +} + +func (u *User) Dir() string { + dir := path.Join(DATA_DIR, u.Email) + if err := os.MkdirAll(dir, 0755); err != nil { + panic(err) + } + return dir +} + +func (u *User) FilePath(name string) string { + return path.Join(u.Dir(), name) +} + +func (u *User) File(name string, mode int) (*os.File, error) { + return os.OpenFile(u.FilePath(name), mode, 0644) +} + +func (u *User) AppendFile(name string) (*os.File, error) { + return u.File(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND) +} + +func (u *User) ReadFile(name string) (*os.File, error) { + return u.File(name, os.O_RDONLY|os.O_CREATE) +} + +func (u *User) WriteFile(name string) (*os.File, error) { + return u.File(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC) +} + +func (u *User) List() ([]string, error) { + files, err := os.ReadDir(u.Dir()) + if err != nil { + panic(err) + } + result := make([]string, len(files)) + for i, v := range files { + result[i] = v.Name() + } + return result, nil +} + +func (u *User) appendToFile(tx string) (err error) { + f, err := u.AppendFile(DEFAULT_JOURNAL) + if err != nil { + return err + } + defer f.Close() + + buf := strings.NewReader(strings.ReplaceAll(tx, "\r", "")) // Remove CR generated from browser + _, err = io.Copy(f, buf) + return err +} + +func (u *User) overwriteFile(filename string, tx string) (err error) { + f, err := u.WriteFile(filename) + if err != nil { + return err + } + defer f.Close() + + buf := strings.NewReader(strings.ReplaceAll(tx, "\r", "")) // Remove CR generated from browser + _, err = io.Copy(f, buf) + return err +} + +func (u *User) query(query string) (result string, err error) { + var buf bytes.Buffer + + cmd := exec.Command("ledger", "--file", DEFAULT_JOURNAL) + cmd.Dir = u.Dir() + cmd.Stdin = strings.NewReader(query) + cmd.Stdout = &buf + cmd.Stderr = &buf + err = cmd.Run() + return buf.String(), err +} + +func (u *User) scripts() (scripts map[string]string, err error) { + f, err := u.ReadFile(SCRIPTS_FILE) + if err != nil { + panic(err) + } + defer f.Close() + + fileScanner := bufio.NewScanner(f) + fileScanner.Split(bufio.ScanLines) + + scripts = make(map[string]string) + for fileScanner.Scan() { + arr := strings.SplitN(fileScanner.Text(), ":", 2) + if len(arr) < 2 { + err = fmt.Errorf("invalid data %s", arr) + return + } + scripts[arr[0]] = arr[1] + } + return +} + +func (u *User) templates() (templates []string, err error) { + files, err := u.List() + if err != nil { + return + } + for _, v := range files { + if strings.HasSuffix(v, ".tpl") { + templates = append(templates, v) + } + } + log.Println(templates) + return +} + +type TxData struct { + Action string `form:"action" binding:"required"` + Name string `form:"name"` + Date string + Amount string `form:"amount" binding:"required"` + Destination string `form:"dest"` + Source string `form:"src"` +} + +func newTx(data TxData) (result string, err error) { + data.Date = time.Now().Format("2006/01/02") + var buf bytes.Buffer + err = ledgerTpl.ExecuteTemplate(&buf, data.Action, data) + return buf.String(), nil +} diff --git a/route.go b/route.go index ca86200..20da0a8 100644 --- a/route.go +++ b/route.go @@ -3,7 +3,6 @@ package main import ( "io/ioutil" "log" - "text/template" "github.com/gin-gonic/gin" ) @@ -31,12 +30,18 @@ func router() *gin.Engine { authZone := r.Group("", authenticate) authZone.GET("/dashboard", func(c *gin.Context) { - HTML(c, 200, "dashboard.html", struct { - Templates []*template.Template - Scripts map[string]string - }{ - ledgerTpl.Templates(), - SCRIPTS, + user := getUser(c) + scripts, err := user.scripts() + if err != nil { + panic(err) + } + templates, err := user.templates() + if err != nil { + panic(err) + } + HTML(c, 200, "dashboard.html", gin.H{ + "Scripts": scripts, + "Templates": templates, }) }) @@ -118,14 +123,18 @@ func router() *gin.Engine { }) authZone.GET("/query", func(c *gin.Context) { + user := getUser(c) response := struct { Query string Result string Scripts map[string]string - }{Scripts: SCRIPTS} - user := getUser(c) + }{} var ok bool var err error + response.Scripts, err = user.scripts() + if err != nil { + panic(err) + } response.Query, ok = c.GetQuery("query") if ok && response.Query != "" { response.Result, err = user.query(response.Query) diff --git a/templates/dashboard.html b/templates/dashboard.html index f7dbb0a..ed336bf 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -3,7 +3,7 @@