mirror of https://github.com/JustKato/FreePad.git
+ Handle post data
This commit is contained in:
parent
a76b9d02ba
commit
051a8a311c
|
@ -15,3 +15,6 @@ API_BAN_LIMIT=300
|
|||
|
||||
# Wether or not to run it all in dev-mode
|
||||
DEV_MODE=0
|
||||
|
||||
# Maximum file storage age in minutes
|
||||
CLEANUP_MAX_AGE=1
|
|
@ -2,4 +2,4 @@ dev/*
|
|||
!dev/.keep
|
||||
.env
|
||||
docker-compose.yaml
|
||||
data/Hello World
|
||||
data
|
2
go.mod
2
go.mod
|
@ -5,5 +5,5 @@ go 1.15
|
|||
require (
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/joho/godotenv v1.4.0
|
||||
github.com/mrz1836/go-sanitize v1.1.5 // indirect
|
||||
github.com/mrz1836/go-sanitize v1.1.5
|
||||
)
|
||||
|
|
3
go.sum
3
go.sum
|
@ -34,8 +34,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
|
@ -57,4 +57,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -6,8 +6,9 @@ import (
|
|||
)
|
||||
|
||||
type Post struct {
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Name string `json:"name"`
|
||||
LastModified string `json:"last_modified"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func getStorageDirectory() string {
|
||||
|
@ -39,16 +40,14 @@ func GetPost(fileName string) Post {
|
|||
// Generate the file path
|
||||
filePath := fmt.Sprintf("%s%s", storageDir, fileName)
|
||||
|
||||
fmt.Println("Reading: ", filePath)
|
||||
|
||||
p := Post{
|
||||
Name: fileName,
|
||||
Content: "",
|
||||
Name: fileName,
|
||||
Content: "",
|
||||
LastModified: "Never Before",
|
||||
}
|
||||
|
||||
// Check if the file exits
|
||||
if _, err := os.Stat(filePath); !os.IsNotExist(err) {
|
||||
fmt.Println("Found ", filePath)
|
||||
// File does exist, read it and set the content
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
|
@ -57,7 +56,14 @@ func GetPost(fileName string) Post {
|
|||
|
||||
// Get the content of the file and put it in the response
|
||||
p.Content = string(data)
|
||||
fmt.Println("Loaded content for ", filePath)
|
||||
|
||||
// Get last modified date
|
||||
fileData, err := os.Stat(filePath)
|
||||
if err == nil {
|
||||
p.LastModified = fileData.ModTime().Format("02/01/2006 03:04:05 PM")
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
|
@ -65,5 +71,26 @@ func GetPost(fileName string) Post {
|
|||
|
||||
func WritePost(p Post) error {
|
||||
|
||||
// Get the base storage directory and make sure it exists
|
||||
storageDir := getStorageDirectory()
|
||||
|
||||
// Generate the file path
|
||||
filePath := fmt.Sprintf("%s%s", storageDir, p.Name)
|
||||
|
||||
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the contnets
|
||||
_, err = f.WriteString(p.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/JustKato/FreePad/lib/helper"
|
||||
"github.com/JustKato/FreePad/lib/objects"
|
||||
|
@ -23,7 +23,27 @@ func HomeRoutes(router *gin.Engine) {
|
|||
// Get the post we are looking for.
|
||||
postName := c.Param("post")
|
||||
|
||||
fmt.Println("Sanitizing ", postName)
|
||||
// Sanitize the postName
|
||||
newPostName, err := url.QueryUnescape(postName)
|
||||
if err == nil {
|
||||
postName = newPostName
|
||||
}
|
||||
postName = sanitize.AlphaNumeric(postName, true)
|
||||
|
||||
post := objects.GetPost(postName)
|
||||
|
||||
c.HTML(200, "page.html", gin.H{
|
||||
"title": postName,
|
||||
"post_content": post.Content,
|
||||
"last_modified": post.LastModified,
|
||||
"domain_base": helper.GetDomainBase(),
|
||||
})
|
||||
})
|
||||
|
||||
router.POST("/:post", func(c *gin.Context) {
|
||||
// Get the post we are looking for.
|
||||
postName := c.Param("post")
|
||||
postContent := c.PostForm("content")
|
||||
|
||||
// Sanitize the postName
|
||||
newPostName, err := url.QueryUnescape(postName)
|
||||
|
@ -32,14 +52,26 @@ func HomeRoutes(router *gin.Engine) {
|
|||
}
|
||||
postName = sanitize.AlphaNumeric(postName, true)
|
||||
|
||||
fmt.Println("Fetching ", postName)
|
||||
p := objects.Post{
|
||||
Name: postName,
|
||||
Content: postContent,
|
||||
LastModified: time.Now().Format("02/01/2006 03:04:05 PM"),
|
||||
}
|
||||
|
||||
post := objects.GetPost(postName)
|
||||
// Write the post
|
||||
err = objects.WritePost(p)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err,
|
||||
})
|
||||
|
||||
c.HTML(200, "page.html", gin.H{
|
||||
"title": postName,
|
||||
"post_content": post.Content,
|
||||
"domain_base": helper.GetDomainBase(),
|
||||
// End
|
||||
return
|
||||
}
|
||||
|
||||
// Return the success message
|
||||
c.JSON(200, gin.H{
|
||||
"pad": p,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
4
main.go
4
main.go
|
@ -13,8 +13,8 @@ func main() {
|
|||
// Load environment variables, ignore if any errors come up
|
||||
godotenv.Load()
|
||||
|
||||
_, isDevelopment := os.LookupEnv("DEV_MODE")
|
||||
if isDevelopment {
|
||||
dm, isDevelopment := os.LookupEnv("DEV_MODE")
|
||||
if !isDevelopment && dm == "0" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,21 @@
|
|||
|
||||
</div>
|
||||
|
||||
<textarea name="pad-content" id="pad-content"
|
||||
class="form-control">{{.post_content}}</textarea>
|
||||
<textarea name="pad-content" id="pad-content" onchange="sendMyData(this)" onkeydown="updateStatus(`Not Saved`, `text-danger`)" class="form-control">{{.post_content}}</textarea>
|
||||
|
||||
<div id="pad-status" class="my-4 row">
|
||||
<div class="col-md-12 col-lg-6 col-xl-6" title="Current Viewers">
|
||||
<div class="col-md-12 col-lg-4 col-xl-4" title="Status">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reception-3" viewBox="0 0 16 16">
|
||||
<path d="M0 11.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-5zm4-3a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-8zm4 8a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" readonly value="Loaded" id="loading_status">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 col-lg-4 col-xl-4 mt-4 mt-lg-0 mt-xl-0" title="Current Viewers">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
|
||||
|
@ -33,14 +43,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 col-lg-6 col-xl-6 mt-4 mt-lg-0 mt-xl-0" title="Last Modified">
|
||||
<div class="col-md-12 col-lg-4 col-xl-4 mt-4 mt-lg-0 mt-xl-0" title="Last Modified">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hourglass-split" viewBox="0 0 16 16">
|
||||
<path d="M2.5 15a.5.5 0 1 1 0-1h1v-1a4.5 4.5 0 0 1 2.557-4.06c.29-.139.443-.377.443-.59v-.7c0-.213-.154-.451-.443-.59A4.5 4.5 0 0 1 3.5 3V2h-1a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-1v1a4.5 4.5 0 0 1-2.557 4.06c-.29.139-.443.377-.443.59v.7c0 .213.154.451.443.59A4.5 4.5 0 0 1 12.5 13v1h1a.5.5 0 0 1 0 1h-11zm2-13v1c0 .537.12 1.045.337 1.5h6.326c.216-.455.337-.963.337-1.5V2h-7zm3 6.35c0 .701-.478 1.236-1.011 1.492A3.5 3.5 0 0 0 4.5 13s.866-1.299 3-1.48V8.35zm1 0v3.17c2.134.181 3 1.48 3 1.48a3.5 3.5 0 0 0-1.989-3.158C8.978 9.586 8.5 9.052 8.5 8.351z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input type="text" class="form-control" readonly value="Never Before">
|
||||
<input type="text" class="form-control" id="last_modified_" readonly value="{{.last_modified}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -60,4 +70,58 @@
|
|||
{{ template "inc/theme-toggle.html" .}}
|
||||
</body>
|
||||
|
||||
<script>
|
||||
function sendMyData(el) {
|
||||
const formData = new FormData();
|
||||
|
||||
el.setAttribute(`readonly`, `1`);
|
||||
|
||||
formData.set("content", el.value);
|
||||
|
||||
updateStatus(`Attempting to save...`, `text-warning`);
|
||||
|
||||
fetch(window.location.href.toString(), {
|
||||
body: formData,
|
||||
method: "post",
|
||||
})
|
||||
.then( resp => {
|
||||
console.log(resp);
|
||||
resp.json()
|
||||
.then( e => {
|
||||
console.log(e.pad);
|
||||
|
||||
document.getElementById(`last_modified_`).value = e.pad.last_modified;
|
||||
updateStatus(`Succesfully Saved`, `text-success`);
|
||||
})
|
||||
.catch( err => {
|
||||
console.error(err);
|
||||
updateStatus(`Failed to Save`, `text-error`);
|
||||
})
|
||||
})
|
||||
.catch( err => {
|
||||
console.error(err);
|
||||
updateStatus(`Failed to Save`, `text-error`);
|
||||
})
|
||||
.finally( () => {
|
||||
el.removeAttribute(`readonly`);
|
||||
})
|
||||
}
|
||||
|
||||
function updateStatus(txt, cls) {
|
||||
|
||||
const loading_status = document.getElementById(`loading_status`)
|
||||
|
||||
loading_status.value = txt;
|
||||
|
||||
loading_status.classList.remove("text-danger", "text-warning", "text-success", "text-white", "text-primary");
|
||||
|
||||
loading_status.classList.add(cls);
|
||||
}
|
||||
|
||||
document.addEventListener(`DOMContentLoaded`, e => {
|
||||
document.getElementById(`pad-content`).focus();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
{{ template "inc/footer.html" .}}
|
Loading…
Reference in New Issue