Add user dir & file

This commit is contained in:
Wancat
2022-11-04 23:06:32 +08:00
parent bca1735393
commit 9f99aad680
6 changed files with 149 additions and 109 deletions

102
main.go
View File

@@ -4,10 +4,8 @@ import (
"encoding/base64" "encoding/base64"
"flag" "flag"
"log" "log"
"net/http"
"text/template" "text/template"
"github.com/gin-gonic/gin"
"github.com/gorilla/securecookie" "github.com/gorilla/securecookie"
"github.com/lancatlin/ledger-quicknote/auth" "github.com/lancatlin/ledger-quicknote/auth"
) )
@@ -15,26 +13,17 @@ import (
var ledgerTpl *template.Template var ledgerTpl *template.Template
var htmlTpl *template.Template var htmlTpl *template.Template
var LEDGER_FILE string var DATA_DIR string
var LEDGER_INIT string
var WORKING_DIR string
var HOST string var HOST string
var store auth.AuthStore var store auth.AuthStore
const HTPASSWD_FILE = ".htpasswd" const HTPASSWD_FILE = ".htpasswd"
const DEFAULT_JOURNAL = "ledger.txt"
type UserLogin struct {
IsLogin bool
Email string `form:"email" binding:"required"`
Password string `form:"password" binding:"required"`
}
func init() { func init() {
ledgerTpl = template.Must(template.ParseGlob("tx/*")) ledgerTpl = template.Must(template.ParseGlob("tx/*"))
flag.StringVar(&LEDGER_FILE, "f", "example.txt", "ledger journal file to write") flag.StringVar(&DATA_DIR, "d", "data", "data folder")
flag.StringVar(&LEDGER_INIT, "i", "", "ledger initiation file")
flag.StringVar(&WORKING_DIR, "w", "", "ledger working directory")
flag.StringVar(&HOST, "b", "127.0.0.1:8000", "binding address") flag.StringVar(&HOST, "b", "127.0.0.1:8000", "binding address")
var hashKeyString string var hashKeyString string
flag.StringVar(&hashKeyString, "s", "", "session secret") flag.StringVar(&hashKeyString, "s", "", "session secret")
@@ -59,90 +48,7 @@ func init() {
} }
func main() { func main() {
r := gin.Default() r := router()
r.HTMLRender = loadTemplates("templates")
r.GET("/", func(c *gin.Context) {
HTML(c, 200, "index.html", nil)
})
r.GET("/signup", func(c *gin.Context) {
HTML(c, 200, "signup.html", nil)
})
r.GET("/signin", func(c *gin.Context) {
HTML(c, 200, "signin.html", nil)
})
r.POST("/signup", signup)
r.POST("/signin", signin)
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,
})
})
authZone.POST("/new", func(c *gin.Context) {
var data TxData
if err := c.ShouldBind(&data); err != nil {
c.AbortWithError(400, err)
return
}
tx, err := newTx(data)
if err != nil {
c.AbortWithError(400, err)
log.Println(err, c.Request.Form)
return
}
HTML(c, 200, "new.html", struct {
Tx string
}{tx})
})
authZone.POST("/submit", func(c *gin.Context) {
tx := c.PostForm("tx")
if err := appendToFile(tx); err != nil {
c.AbortWithError(500, err)
return
}
HTML(c, 200, "success.html", struct {
Tx string
}{tx})
})
authZone.GET("/exec", func(c *gin.Context) {
name, _ := c.GetQuery("name")
if err := executeScript(c.Writer, name); err != nil {
c.AbortWithError(500, err)
log.Println(err)
return
}
})
log.Fatal(r.Run(HOST)) log.Fatal(r.Run(HOST))
} }
func authenticate(c *gin.Context) {
cookie, err := c.Cookie("session")
if err == http.ErrNoCookie {
c.Redirect(303, "/signin")
return
}
session, err := store.Verify(cookie)
if err != nil {
c.Redirect(303, "/signin")
return
}
c.Set("user", UserLogin{
Email: session.User,
})
c.Next()
}

82
route.go Normal file
View File

@@ -0,0 +1,82 @@
package main
import (
"log"
"text/template"
"github.com/gin-gonic/gin"
)
func router() *gin.Engine {
r := gin.Default()
r.HTMLRender = loadTemplates("templates")
r.GET("/", func(c *gin.Context) {
HTML(c, 200, "index.html", nil)
})
r.GET("/signup", func(c *gin.Context) {
HTML(c, 200, "signup.html", nil)
})
r.GET("/signin", func(c *gin.Context) {
HTML(c, 200, "signin.html", nil)
})
r.POST("/signup", signup)
r.POST("/signin", signin)
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,
})
})
authZone.POST("/new", func(c *gin.Context) {
var data TxData
if err := c.ShouldBind(&data); err != nil {
c.AbortWithError(400, err)
return
}
tx, err := newTx(data)
if err != nil {
c.AbortWithError(400, err)
log.Println(err, c.Request.Form)
return
}
HTML(c, 200, "new.html", struct {
Tx string
}{tx})
})
authZone.POST("/submit", func(c *gin.Context) {
user := getUser(c)
tx := c.PostForm("tx")
if err := user.appendToFile(tx); err != nil {
c.AbortWithError(500, err)
return
}
HTML(c, 200, "success.html", struct {
Tx string
}{tx})
})
authZone.GET("/exec", func(c *gin.Context) {
user := getUser(c)
name, _ := c.GetQuery("name")
if err := user.executeScript(c.Writer, name); err != nil {
c.AbortWithError(500, err)
log.Println(err)
return
}
})
return r
}

View File

@@ -1,9 +1,34 @@
package main package main
import "github.com/gin-gonic/gin" import (
"net/http"
"github.com/gin-gonic/gin"
)
func authenticate(c *gin.Context) {
cookie, err := c.Cookie("session")
if err == http.ErrNoCookie {
c.Redirect(303, "/signin")
return
}
session, err := store.Verify(cookie)
if err != nil {
c.Redirect(303, "/signin")
return
}
c.Set("user", User{
Email: session.User,
})
c.Next()
}
func getUser(c *gin.Context) User {
return c.MustGet("user").(User)
}
func signup(c *gin.Context) { func signup(c *gin.Context) {
var user UserLogin var user User
if err := c.ShouldBind(&user); err != nil { if err := c.ShouldBind(&user); err != nil {
HTML(c, 400, "signup.html", err) HTML(c, 400, "signup.html", err)
return return
@@ -16,7 +41,7 @@ func signup(c *gin.Context) {
} }
func signin(c *gin.Context) { func signin(c *gin.Context) {
var user UserLogin var user User
if err := c.ShouldBind(&user); err != nil { if err := c.ShouldBind(&user); err != nil {
HTML(c, 400, "signin.html", err) HTML(c, 400, "signin.html", err)
return return

View File

@@ -31,7 +31,7 @@ type Data interface{}
type Page struct { type Page struct {
Data Data
User UserLogin User User
} }
func HTML(c *gin.Context, status int, name string, data interface{}) { func HTML(c *gin.Context, status int, name string, data interface{}) {
@@ -40,7 +40,7 @@ func HTML(c *gin.Context, status int, name string, data interface{}) {
} }
_, ok := c.Get("user") _, ok := c.Get("user")
if ok { if ok {
output.User = c.MustGet("user").(UserLogin) output.User = c.MustGet("user").(User)
} }
c.HTML(status, name, output) c.HTML(status, name, output)
} }

11
tx.go
View File

@@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"os"
"os/exec" "os/exec"
"strings" "strings"
"time" "time"
@@ -25,8 +24,8 @@ func newTx(data TxData) (result string, err error) {
return buf.String(), nil return buf.String(), nil
} }
func appendToFile(tx string) (err error) { func (u *User) appendToFile(tx string) (err error) {
f, err := os.OpenFile(LEDGER_FILE, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) f, err := u.File(DEFAULT_JOURNAL)
if err != nil { if err != nil {
return err return err
} }
@@ -37,13 +36,13 @@ func appendToFile(tx string) (err error) {
return err return err
} }
func executeScript(w io.Writer, name string) (err error) { func (u *User) executeScript(w io.Writer, name string) (err error) {
script, ok := SCRIPTS[name] script, ok := SCRIPTS[name]
if !ok { if !ok {
return fmt.Errorf("%s script not found", name) return fmt.Errorf("%s script not found", name)
} }
cmd := exec.Command("ledger", append([]string{"--init-file", LEDGER_INIT, "--file", LEDGER_FILE}, script...)...) cmd := exec.Command("ledger", append([]string{"--file", DEFAULT_JOURNAL}, script...)...)
cmd.Dir = WORKING_DIR cmd.Dir = u.Dir()
cmd.Stdout = w cmd.Stdout = w
cmd.Stderr = w cmd.Stderr = w
return cmd.Run() return cmd.Run()

28
user.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"os"
"path"
)
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(DATA_DIR, u.Email, name)
}
func (u *User) File(name string) (*os.File, error) {
return os.OpenFile(u.FilePath(name), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
}