1
0
mirror of https://github.com/schollz/cowyo.git synced 2023-08-10 21:13:00 +03:00

Reorganize and add migration

Former-commit-id: 807d525f11b5306c2a4a2e7097a8d92d026fc9df [formerly 9c40fcf478e90dd062c9a173b4d563a4ba15b8bc] [formerly 0c56b23e0782fe14717c243d149983185fe9ad2d [formerly 7f4acdda9a]]
Former-commit-id: 71ae3d9712ec1b7203e6483ad586aeef319fba08 [formerly e633558e9a7491044e324ceeb2cb699b2130f1c8]
Former-commit-id: 8e483f94bf5c75d62d00219085d1e68c4e5683c7
This commit is contained in:
Zack Scholl 2017-03-21 21:51:52 -06:00
parent 97edbd73a8
commit 8a7803250f
5 changed files with 282 additions and 174 deletions

178
handlers.go Executable file
View File

@ -0,0 +1,178 @@
package main
import (
"html/template"
"net/http"
"strconv"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
)
func serve() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.Use(static.Serve("/static/", static.LocalFile("./static", true)))
router.GET("/", func(c *gin.Context) {
c.Redirect(302, "/"+randomAlliterateCombo())
})
router.GET("/:page", func(c *gin.Context) {
page := c.Param("page")
c.Redirect(302, "/"+page+"/edit")
})
router.GET("/:page/:command", handlePageRequest)
router.POST("/update", handlePageUpdate)
router.POST("/prime", handlePrime)
router.POST("/lock", handleLock)
router.POST("/encrypt", handleEncrypt)
router.Run(":8050")
}
func handlePageRequest(c *gin.Context) {
page := c.Param("page")
command := c.Param("command")
version := c.DefaultQuery("version", "ajksldfjl")
p := Open(page)
if p.IsPrimedForSelfDestruct && !p.IsLocked {
p.Update("*This page has now self-destructed.*\n\n" + p.Text.GetCurrent())
p.Erase()
}
if command == "erase" && !p.IsLocked {
p.Erase()
c.Redirect(302, "/"+page+"/edit")
}
rawText := p.Text.GetCurrent()
rawHTML := p.RenderedPage
// Check to see if an old version is requested
versionInt, versionErr := strconv.Atoi(version)
if versionErr == nil && versionInt > 0 {
versionText, err := p.Text.GetPreviousByTimestamp(int64(versionInt))
if err == nil {
rawText = versionText
rawHTML = MarkdownToHtml(rawText)
}
}
c.HTML(http.StatusOK, "index.html", gin.H{
"EditPage": command == "edit",
"ViewPage": command == "view",
"ListPage": command == "list",
"HistoryPage": command == "history",
"Page": p.Name,
"RenderedPage": template.HTML([]byte(rawHTML)),
"RawPage": rawText,
"Versions": p.Text.GetSnapshots(),
"IsLocked": p.IsLocked,
"IsEncrypted": p.IsEncrypted,
})
}
func handlePageUpdate(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
NewText string `json:"new_text"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
log.Trace("Update: %v", json)
p := Open(json.Page)
var message string
if p.IsLocked {
message = "Locked"
} else if p.IsEncrypted {
message = "Encrypted"
} else {
p.Update(json.NewText)
p.Save()
message = "Saved"
}
c.JSON(http.StatusOK, gin.H{"success": false, "message": message})
}
func handlePrime(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
log.Trace("Update: %v", json)
p := Open(json.Page)
p.IsPrimedForSelfDestruct = true
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true})
}
func handleLock(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
Passphrase string `json:"passphrase"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
p := Open(json.Page)
var message string
if p.IsLocked {
err2 := CheckPasswordHash(json.Passphrase, p.PassphraseToUnlock)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "message": "Can't unlock"})
return
}
p.IsLocked = false
message = "Unlocked"
} else {
p.IsLocked = true
p.PassphraseToUnlock = HashPassword(json.Passphrase)
message = "Locked"
}
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true, "message": message})
}
func handleEncrypt(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
Passphrase string `json:"passphrase"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
p := Open(json.Page)
var message string
if p.IsEncrypted {
decrypted, err2 := DecryptString(p.Text.GetCurrent(), json.Passphrase)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "message": "Wrong password"})
return
}
p.Erase()
p = Open(json.Page)
p.Update(decrypted)
p.IsEncrypted = false
message = "Decrypted"
} else {
currentText := p.Text.GetCurrent()
p.Erase()
p = Open(json.Page)
p.IsEncrypted = true
encrypted, _ := EncryptString(currentText, json.Passphrase)
p.Update(encrypted)
message = "Encrypted"
}
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true, "message": message})
}

234
main.go
View File

@ -1,178 +1,76 @@
package main
import (
"html/template"
"net/http"
"strconv"
"fmt"
"os"
"time"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
"gopkg.in/urfave/cli.v1"
)
var version string
var pathToData string
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.Use(static.Serve("/static/", static.LocalFile("./static", true)))
app := cli.NewApp()
app.Name = "linkcrawler"
app.Usage = "crawl a site for links, or download a list of sites"
app.Version = version
app.Compiled = time.Now()
app.Action = func(c *cli.Context) error {
cli.ShowSubcommandHelp(c)
return nil
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "data",
Value: "data",
Usage: "data folder to use",
},
cli.StringFlag{
Name: "olddata",
Value: "",
Usage: "data folder for migrating",
},
cli.BoolFlag{
Name: "debug, d",
Usage: "turn on debugging",
},
}
app.Commands = []cli.Command{
{
Name: "serve",
Aliases: []string{"s"},
Usage: "start a cowyo server",
Action: func(c *cli.Context) error {
pathToData = c.GlobalString("data")
os.MkdirAll(pathToData, 0755)
serve()
return nil
},
},
{
Name: "migrate",
Aliases: []string{"m"},
Usage: "migrate from the old cowyo",
Action: func(c *cli.Context) error {
pathToData = c.GlobalString("data")
pathToOldData := c.GlobalString("olddata")
if len(pathToOldData) == 0 {
fmt.Printf("You need to specify folder with -olddata")
return nil
}
os.MkdirAll(pathToData, 0755)
if !exists(pathToOldData) {
fmt.Printf("Can not find '%s', does it exist?", pathToOldData)
return nil
}
migrate(pathToOldData, pathToData)
return nil
},
},
}
router.GET("/", func(c *gin.Context) {
c.Redirect(302, "/"+randomAlliterateCombo())
})
router.GET("/:page", func(c *gin.Context) {
page := c.Param("page")
c.Redirect(302, "/"+page+"/edit")
})
router.GET("/:page/:command", handlePageRequest)
router.POST("/update", handlePageUpdate)
router.POST("/prime", handlePrime)
router.POST("/lock", handleLock)
router.POST("/encrypt", handleEncrypt)
app.Run(os.Args)
router.Run(":8050")
}
func handlePageRequest(c *gin.Context) {
page := c.Param("page")
command := c.Param("command")
version := c.DefaultQuery("version", "ajksldfjl")
p := Open(page)
if p.IsPrimedForSelfDestruct && !p.IsLocked {
p.Update("*This page has now self-destructed.*\n\n" + p.Text.GetCurrent())
p.Erase()
}
if command == "erase" && !p.IsLocked {
p.Erase()
c.Redirect(302, "/"+page+"/edit")
}
rawText := p.Text.GetCurrent()
rawHTML := p.RenderedPage
// Check to see if an old version is requested
versionInt, versionErr := strconv.Atoi(version)
if versionErr == nil && versionInt > 0 {
versionText, err := p.Text.GetPreviousByTimestamp(int64(versionInt))
if err == nil {
rawText = versionText
rawHTML = MarkdownToHtml(rawText)
}
}
c.HTML(http.StatusOK, "index.html", gin.H{
"EditPage": command == "edit",
"ViewPage": command == "view",
"ListPage": command == "list",
"HistoryPage": command == "history",
"Page": p.Name,
"RenderedPage": template.HTML([]byte(rawHTML)),
"RawPage": rawText,
"Versions": p.Text.GetSnapshots(),
"IsLocked": p.IsLocked,
"IsEncrypted": p.IsEncrypted,
})
}
func handlePageUpdate(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
NewText string `json:"new_text"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
log.Trace("Update: %v", json)
p := Open(json.Page)
var message string
if p.IsLocked {
message = "Locked"
} else if p.IsEncrypted {
message = "Encrypted"
} else {
p.Update(json.NewText)
p.Save()
message = "Saved"
}
c.JSON(http.StatusOK, gin.H{"success": false, "message": message})
}
func handlePrime(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
log.Trace("Update: %v", json)
p := Open(json.Page)
p.IsPrimedForSelfDestruct = true
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true})
}
func handleLock(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
Passphrase string `json:"passphrase"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
p := Open(json.Page)
var message string
if p.IsLocked {
err2 := CheckPasswordHash(json.Passphrase, p.PassphraseToUnlock)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "message": "Can't unlock"})
return
}
p.IsLocked = false
message = "Unlocked"
} else {
p.IsLocked = true
p.PassphraseToUnlock = HashPassword(json.Passphrase)
message = "Locked"
}
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true, "message": message})
}
func handleEncrypt(c *gin.Context) {
type QueryJSON struct {
Page string `json:"page"`
Passphrase string `json:"passphrase"`
}
var json QueryJSON
if c.BindJSON(&json) != nil {
c.String(http.StatusBadRequest, "Problem binding keys")
return
}
p := Open(json.Page)
var message string
if p.IsEncrypted {
decrypted, err2 := DecryptString(p.Text.GetCurrent(), json.Passphrase)
if err2 != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "message": "Wrong password"})
return
}
p.Erase()
p = Open(json.Page)
p.Update(decrypted)
p.IsEncrypted = false
message = "Decrypted"
} else {
currentText := p.Text.GetCurrent()
p.Erase()
p = Open(json.Page)
p.IsEncrypted = true
encrypted, _ := EncryptString(currentText, json.Passphrase)
p.Update(encrypted)
message = "Encrypted"
}
p.Save()
c.JSON(http.StatusOK, gin.H{"success": true, "message": message})
}

25
migrate.go Executable file
View File

@ -0,0 +1,25 @@
package main
import (
"fmt"
"io/ioutil"
"path"
)
func migrate(pathToOldData, pathToData string) error {
files, _ := ioutil.ReadDir(pathToOldData)
for _, f := range files {
fmt.Printf("Migrating %s", f.Name())
p := Open(f.Name())
bData, err := ioutil.ReadFile(path.Join(pathToOldData, f.Name()))
if err != nil {
return err
}
err = p.Update(string(bData))
if err != nil {
return err
}
p.Save()
}
return nil
}

View File

@ -12,12 +12,6 @@ import (
"github.com/schollz/versionedtext"
)
var pathToData = "data"
func init() {
os.MkdirAll(pathToData, 0755)
}
type Page struct {
Name string
Text versionedtext.VersionedText

View File

@ -7,6 +7,7 @@ import (
"io/ioutil"
"math/rand"
"net"
"os"
"strings"
"time"
@ -201,3 +202,15 @@ func DecryptString(toDecrypt string, password string) (string, error) {
bDecrypted, err := cryptopasta.Decrypt(contentData, &key)
return string(bDecrypted), err
}
// exists returns whether the given file or directory exists or not
func exists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return true
}