Add Template layouts, load session hashkey

This commit is contained in:
Wancat
2022-11-04 22:44:25 +08:00
parent bc1095fc61
commit bca1735393
7 changed files with 77 additions and 38 deletions

42
main.go
View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/base64"
"flag" "flag"
"log" "log"
"net/http" "net/http"
@@ -24,6 +25,7 @@ var store auth.AuthStore
const HTPASSWD_FILE = ".htpasswd" const HTPASSWD_FILE = ".htpasswd"
type UserLogin struct { type UserLogin struct {
IsLogin bool
Email string `form:"email" binding:"required"` Email string `form:"email" binding:"required"`
Password string `form:"password" binding:"required"` Password string `form:"password" binding:"required"`
} }
@@ -34,16 +36,23 @@ func init() {
flag.StringVar(&LEDGER_INIT, "i", "", "ledger initiation file") flag.StringVar(&LEDGER_INIT, "i", "", "ledger initiation file")
flag.StringVar(&WORKING_DIR, "w", "", "ledger working directory") 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 hashKey string var hashKeyString string
flag.StringVar(&hashKey, "s", "", "session secret") flag.StringVar(&hashKeyString, "s", "", "session secret")
flag.Parse() flag.Parse()
if hashKey == "" { var hashKey []byte
hashKey = string(securecookie.GenerateRandomKey(32))
log.Printf("Generate random session key: %s", hashKey)
}
var err error var err error
store, err = auth.New(HTPASSWD_FILE, []byte(hashKey))
if hashKeyString == "" {
hashKey = securecookie.GenerateRandomKey(32)
log.Printf("Generate random session key: %s", base64.StdEncoding.EncodeToString(hashKey))
} else {
hashKey, err = base64.StdEncoding.DecodeString(hashKeyString)
if err != nil {
panic(err)
}
}
store, err = auth.New(HTPASSWD_FILE, hashKey)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -53,22 +62,26 @@ func main() {
r := gin.Default() r := gin.Default()
r.HTMLRender = loadTemplates("templates") r.HTMLRender = loadTemplates("templates")
r.GET("/", func(c *gin.Context) {
HTML(c, 200, "index.html", nil)
})
r.GET("/signup", func(c *gin.Context) { r.GET("/signup", func(c *gin.Context) {
c.HTML(200, "signup.html", nil) HTML(c, 200, "signup.html", nil)
}) })
r.GET("/signin", func(c *gin.Context) { r.GET("/signin", func(c *gin.Context) {
c.HTML(200, "signin.html", nil) HTML(c, 200, "signin.html", nil)
}) })
r.POST("/signup", signup) r.POST("/signup", signup)
r.POST("/signin", signin) r.POST("/signin", signin)
authZone := r.Group("", basicAuth) authZone := r.Group("", authenticate)
authZone.GET("/dashboard", func(c *gin.Context) { authZone.GET("/dashboard", func(c *gin.Context) {
c.HTML(200, "index.html", struct { HTML(c, 200, "dashboard.html", struct {
Templates []*template.Template Templates []*template.Template
Scripts map[string][]string Scripts map[string][]string
}{ }{
@@ -89,11 +102,10 @@ func main() {
log.Println(err, c.Request.Form) log.Println(err, c.Request.Form)
return return
} }
c.HTML(200, "new.html", struct { HTML(c, 200, "new.html", struct {
Tx string Tx string
}{tx}) }{tx})
}) })
authZone.POST("/submit", func(c *gin.Context) { authZone.POST("/submit", func(c *gin.Context) {
tx := c.PostForm("tx") tx := c.PostForm("tx")
if err := appendToFile(tx); err != nil { if err := appendToFile(tx); err != nil {
@@ -101,7 +113,7 @@ func main() {
return return
} }
c.HTML(200, "success.html", struct { HTML(c, 200, "success.html", struct {
Tx string Tx string
}{tx}) }{tx})
}) })
@@ -118,7 +130,7 @@ func main() {
log.Fatal(r.Run(HOST)) log.Fatal(r.Run(HOST))
} }
func basicAuth(c *gin.Context) { func authenticate(c *gin.Context) {
cookie, err := c.Cookie("session") cookie, err := c.Cookie("session")
if err == http.ErrNoCookie { if err == http.ErrNoCookie {
c.Redirect(303, "/signin") c.Redirect(303, "/signin")

View File

@@ -5,11 +5,11 @@ import "github.com/gin-gonic/gin"
func signup(c *gin.Context) { func signup(c *gin.Context) {
var user UserLogin var user UserLogin
if err := c.ShouldBind(&user); err != nil { if err := c.ShouldBind(&user); err != nil {
c.HTML(400, "signup.html", err) HTML(c, 400, "signup.html", err)
return return
} }
if err := store.Register(user.Email, user.Password); err != nil { if err := store.Register(user.Email, user.Password); err != nil {
c.HTML(400, "signup.html", err) HTML(c, 400, "signup.html", err)
return return
} }
signin(c) signin(c)
@@ -18,12 +18,12 @@ func signup(c *gin.Context) {
func signin(c *gin.Context) { func signin(c *gin.Context) {
var user UserLogin var user UserLogin
if err := c.ShouldBind(&user); err != nil { if err := c.ShouldBind(&user); err != nil {
c.HTML(400, "signin.html", err) HTML(c, 400, "signin.html", err)
return return
} }
token, err := store.Login(user.Email, user.Password) token, err := store.Login(user.Email, user.Password)
if err != nil { if err != nil {
c.HTML(401, "signin.html", err) HTML(c, 401, "signin.html", err)
return return
} }
c.SetCookie("session", token, 60*60*24*7, "", "", false, false) c.SetCookie("session", token, 60*60*24*7, "", "", false, false)

View File

@@ -5,6 +5,7 @@ import (
"path/filepath" "path/filepath"
"github.com/gin-contrib/multitemplate" "github.com/gin-contrib/multitemplate"
"github.com/gin-gonic/gin"
) )
func loadTemplates(templatesDir string) multitemplate.Renderer { func loadTemplates(templatesDir string) multitemplate.Renderer {
@@ -25,3 +26,21 @@ func loadTemplates(templatesDir string) multitemplate.Renderer {
} }
return r return r
} }
type Data interface{}
type Page struct {
Data
User UserLogin
}
func HTML(c *gin.Context, status int, name string, data interface{}) {
output := Page{
Data: data,
}
_, ok := c.Get("user")
if ok {
output.User = c.MustGet("user").(UserLogin)
}
c.HTML(status, name, output)
}

20
templates/dashboard.html Normal file
View File

@@ -0,0 +1,20 @@
{{ define "main" }}
<h1>Ledger Quick Note</h1>
<form action="/new" method="POST">
<label>Action:
{{ range .Templates }}
<input type="radio" name="action" value="{{ .Name }}">{{ .Name }}</option>
{{ end }}
</label><br>
<label>Amount: <input name="amount" type="number"></label><br>
<label>Account: <input name="account" type="text"></label></br>
<label>Tx Name: <input name="name" type="text"></label></br>
<input type="submit">
</form>
<h2>Scripts</h2>
<ul>
{{ range $k, $v := .Scripts }}
<li><a href="/exec?name={{ $k }}">{{ $k }}</a></li>
{{ end }}
</ul>
{{ end }}

View File

@@ -1,20 +1,3 @@
{{ define "main" }} {{ define "main" }}
<h1>Ledger Quick Note</h1> <h1>Ledger Quick Note</h1>
<form action="/new" method="POST">
<label>Action:
{{ range .Templates }}
<input type="radio" name="action" value="{{ .Name }}">{{ .Name }}</option>
{{ end }}
</label><br>
<label>Amount: <input name="amount" type="number"></label><br>
<label>Account: <input name="account" type="text"></label></br>
<label>Tx Name: <input name="name" type="text"></label></br>
<input type="submit">
</form>
<h2>Scripts</h2>
<ul>
{{ range $k, $v := .Scripts }}
<li><a href="/exec?name={{ $k }}">{{ $k }}</a></li>
{{ end }}
</ul>
{{ end }} {{ end }}

View File

@@ -5,7 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head> </head>
<body> <body>
{{ block "main" . }} <nav>
{{ with .User }}
{{ .Email }}
{{ end }}
</nav>
{{ block "main" .Data }}
{{ end }} {{ end }}
</body> </body>

View File

@@ -2,5 +2,5 @@
{{ define "main" }} {{ define "main" }}
<p><strong>Success</strong></p> <p><strong>Success</strong></p>
<pre><code>{{ .Tx }}</code></pre> <pre><code>{{ .Tx }}</code></pre>
<p><a href="/">Back to home</a></p> <p><a href="/dashboard">Back to home</a></p>
{{ end }} {{ end }}