Browse Source

Merge pull request #25 from msoedov/restore_session

Restore previous session
Alex Miasoiedov 6 years ago
parent
commit
39531f0825
6 changed files with 110 additions and 60 deletions
  1. 1 0
      .gitignore
  2. 2 2
      app_test.go
  3. 56 0
      auth/auth.go
  4. 25 0
      files/query.go
  5. 24 57
      main.go
  6. 2 1
      templates/index.tmpl

+ 1 - 0
.gitignore

@@ -25,3 +25,4 @@ src/
 slides/
 main
 node_modules
+hacker-slides

+ 2 - 2
app_test.go

@@ -34,10 +34,10 @@ func Test(t *testing.T) {
 	g.Describe("App api", func() {
 		var cookie string
 
-		g.It("Should return 200 on / ", func() {
+		g.It("Should return 302 on / to redirect to file name ", func() {
 			w := client("GET", "/", "")
 
-			g.Assert(w.Code).Equal(200)
+			g.Assert(w.Code).Equal(302)
 			cookie = w.HeaderMap.Get(Cookie)
 		})
 

+ 56 - 0
auth/auth.go

@@ -0,0 +1,56 @@
+package auth
+
+import (
+	"encoding/base64"
+	"fmt"
+	"os"
+	"strconv"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/gin-gonic/gin"
+)
+
+func Header(c *gin.Context, key string) string {
+	if values, _ := c.Request.Header[key]; len(values) > 0 {
+		return values[0]
+	}
+	return ""
+}
+
+func BasicAuth() gin.HandlerFunc {
+	realm := "Authorization Required"
+	realm = "Basic realm=" + strconv.Quote(realm)
+	user := os.Getenv("USER")
+	password := os.Getenv("PASSWORD")
+	enabled := isEnabled(user, password)
+	if enabled {
+		log.Warn("Auth mode enabled")
+		log.Warn(fmt.Sprintf("Visit http://%s:%s@0.0.0.0:8080", user, password))
+	}
+	return func(c *gin.Context) {
+		header := Header(c, "Authorization")
+		if enabled && header != authorizationHeader(user, password) {
+			// Credentials doesn't match, we return 401 and abort handlers chain.
+			c.Header("WWW-Authenticate", realm)
+			c.AbortWithStatus(401)
+			return
+		}
+		c.Next()
+	}
+}
+
+func isEnabled(user, password string) bool {
+	switch {
+	case user == "":
+		return false
+	case password == "":
+		return false
+	default:
+		return true
+	}
+}
+
+func authorizationHeader(user, password string) string {
+	base := user + ":" + password
+	return "Basic " + base64.StdEncoding.EncodeToString([]byte(base))
+}

+ 25 - 0
files/query.go

@@ -0,0 +1,25 @@
+package files
+
+import (
+	"io/ioutil"
+	"time"
+)
+
+var epoch = time.Unix(1494505756, 0)
+
+func LatestFileIn(path string) (latest string) {
+	files, err := ioutil.ReadDir(path)
+	if err != nil {
+		return ""
+	}
+	latestTime := epoch
+	for _, f := range files {
+		path := f.Name()
+		pathModifiedAt := f.ModTime()
+		if pathModifiedAt.After(latestTime) {
+			latestTime = pathModifiedAt
+			latest = path
+		}
+	}
+	return
+}

+ 24 - 57
main.go

@@ -1,65 +1,24 @@
 package main
 
 import (
-	"encoding/base64"
 	"errors"
 	"fmt"
 	"io/ioutil"
 	"os"
-	"strconv"
 	"strings"
 
 	log "github.com/Sirupsen/logrus"
 	haikunator "github.com/atrox/haikunatorgo"
 	"github.com/gin-contrib/sessions"
 	"github.com/gin-gonic/gin"
+	"github.com/msoedov/hacker-slides/auth"
+	"github.com/msoedov/hacker-slides/files"
 )
 
 const sessionHeader = "slide-session"
 
-func Header(c *gin.Context, key string) string {
-	if values, _ := c.Request.Header[key]; len(values) > 0 {
-		return values[0]
-	}
-	return ""
-}
-
-func BasicAuth() gin.HandlerFunc {
-	realm := "Authorization Required"
-	realm = "Basic realm=" + strconv.Quote(realm)
-	user := os.Getenv("USER")
-	password := os.Getenv("PASSWORD")
-	enabled := isEnabled(user, password)
-	if enabled {
-		log.Warn("Auth mode enabled")
-		log.Warn(fmt.Sprintf("Visit http://%s:%s@0.0.0.0:8080", user, password))
-	}
-	return func(c *gin.Context) {
-		header := Header(c, "Authorization")
-		if enabled && header != authorizationHeader(user, password) {
-			// Credentials doesn't match, we return 401 and abort handlers chain.
-			c.Header("WWW-Authenticate", realm)
-			c.AbortWithStatus(401)
-			return
-		}
-		c.Next()
-	}
-}
-
-func isEnabled(user, password string) bool {
-	switch {
-	case user == "":
-		return false
-	case password == "":
-		return false
-	default:
-		return true
-	}
-}
-
-func authorizationHeader(user, password string) string {
-	base := user + ":" + password
-	return "Basic " + base64.StdEncoding.EncodeToString([]byte(base))
+func SlidePath(name string) string {
+	return fmt.Sprintf("slides/%s.md", name)
 }
 
 func NewApp() *gin.Engine {
@@ -68,22 +27,29 @@ func NewApp() *gin.Engine {
 
 	store := sessions.NewCookieStore([]byte("secret"))
 	r.Use(sessions.Sessions(sessionHeader, store))
-	r.Use(BasicAuth())
+	r.Use(auth.BasicAuth())
 
 	r.LoadHTMLGlob("templates/*.tmpl")
 	r.Static("/static", "./static")
 
 	r.GET("/", func(c *gin.Context) {
-
-		fname := c.Param("name")
+		isNew := c.Query("new")
+		latest := files.LatestFileIn("slides")
 		log.WithFields(log.Fields{
-			"name": fname,
-		}).Info("Restore?")
+			"name":  latest,
+			"isNew": isNew,
+		}).Info("Restoring latest point")
+
+		var path, name string
+		if latest == "" || isNew != "" {
+			haikunator := haikunator.New()
+			haikunator.TokenLength = 0
+			name = haikunator.Haikunate()
+		} else {
+			name = strings.Replace(latest, ".md", "", 1)
+		}
+		path = SlidePath(name)
 
-		haikunator := haikunator.New()
-		haikunator.TokenLength = 0
-		name := haikunator.Haikunate()
-		path := fmt.Sprintf("slides/%s.md", name)
 		log.WithFields(log.Fields{
 			"path": path,
 		}).Info("A new session")
@@ -91,7 +57,8 @@ func NewApp() *gin.Engine {
 		session.Set("name", path)
 		session.Save()
 
-		c.HTML(200, "index.tmpl", gin.H{
+		c.Writer.Header().Set("Location", fmt.Sprintf("/stash/edit/%s", name))
+		c.HTML(302, "index.tmpl", gin.H{
 			"pubTo": path,
 		})
 	})
@@ -176,7 +143,7 @@ func NewApp() *gin.Engine {
 		if strings.HasSuffix(name, ".md") {
 			name = name[0 : len(name)-3]
 		}
-		path := fmt.Sprintf("slides/%s.md", name)
+		path := SlidePath(name)
 		session := sessions.Default(c)
 		session.Set("name", path)
 		session.Save()
@@ -196,7 +163,7 @@ func NewApp() *gin.Engine {
 		if strings.HasSuffix(name, ".md") {
 			name = name[0 : len(name)-3]
 		}
-		path := fmt.Sprintf("slides/%s.md", name)
+		path := SlidePath(name)
 		session := sessions.Default(c)
 		session.Set("name", path)
 		session.Save()

+ 2 - 1
templates/index.tmpl

@@ -14,7 +14,8 @@
     <body>
         <div id="edit-pane">
           <div id="controls">
-          <a href="/stash" target="_blank" onclick="save();"> Stash</a> | 
+            <a href="/?new=true" target="_blank" onclick="save();"> New</a> |
+            <a href="/stash" target="_blank" onclick="save();"> Stash</a> |
             <a href="/published/{{ .pubTo}}" target="_blank" onclick="save();"> Present</a> |
             <a href="/published/{{ .pubTo}}?print-pdf" target="_blank" onclick="save();"> Pdf</a>
           </div>