Add Template layouts, load session hashkey
This commit is contained in:
42
main.go
42
main.go
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
19
template.go
19
template.go
@@ -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
20
templates/dashboard.html
Normal 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 }}
|
||||||
@@ -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 }}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 }}
|
||||||
|
|||||||
Reference in New Issue
Block a user