plakken/internal/web/plak/plak.go
Ada 8a88613f89 Implement basic POST request for curl
/ can now read body and create paste, for curl like client, web create with full settings is move to /create
2024-02-24 01:35:26 +01:00

193 lines
4.1 KiB
Go

package plak
import (
"context"
"embed"
"io"
"log"
"net/http"
"time"
"git.gnous.eu/gnouseu/plakken/internal/constant"
"git.gnous.eu/gnouseu/plakken/internal/database"
"git.gnous.eu/gnouseu/plakken/internal/utils"
"github.com/redis/go-redis/v9"
"html/template"
)
var ctx = context.Background()
type WebConfig struct {
DB *redis.Client
UrlLength uint8
Templates embed.FS
}
// Plak "Object" for plak
type Plak struct {
Key string
Content string
Expiration time.Duration
DB *redis.Client
}
// Create manage POST request for create Plak
func (config WebConfig) Create(w http.ResponseWriter, r *http.Request) {
content := r.FormValue("content")
if content == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
dbConf := database.DBConfig{
DB: config.DB,
}
filename := r.FormValue("filename")
var key string
if len(filename) == 0 {
key = utils.GenerateUrl(config.UrlLength)
} else {
if !utils.ValidKey(filename) {
w.WriteHeader(http.StatusBadRequest)
return
}
if dbConf.UrlExist(filename) {
w.WriteHeader(http.StatusBadRequest)
return
}
key = filename
}
secret := utils.GenerateSecret()
rawExpiration := r.FormValue("exp")
expiration, err := utils.ParseExpiration(rawExpiration)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
} else if expiration == 0 {
dbConf.InsertPaste(key, content, secret, -1)
} else {
dbConf.InsertPaste(key, content, secret, time.Duration(expiration*int(time.Second)))
}
http.Redirect(w, r, "/"+key, http.StatusSeeOther)
}
// CurlCreate Create plak with minimum param, ideal for curl. Force 7 day expiration
func (config WebConfig) CurlCreate(w http.ResponseWriter, r *http.Request) {
if r.ContentLength == 0 {
w.WriteHeader(http.StatusBadRequest)
return
}
content, _ := io.ReadAll(r.Body)
err := r.Body.Close()
if err != nil {
log.Println(err)
}
key := utils.GenerateUrl(config.UrlLength)
secret := utils.GenerateSecret()
dbConf := database.DBConfig{
DB: config.DB,
}
dbConf.InsertPaste(key, string(content), secret, constant.ExpirationCurlCreate)
var baseURL string
if r.TLS == nil {
baseURL = "http://" + r.Host + "/" + key
} else {
baseURL = "https://" + r.Host + "/" + key
}
message := baseURL + "\n" + "Delete with : 'curl -X DELETE " + baseURL + "?secret\\=" + secret + "'" + "\n"
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
_, err = io.WriteString(w, message)
if err != nil {
log.Println(err)
}
}
// View for plak
func (config WebConfig) View(w http.ResponseWriter, r *http.Request) {
dbConf := database.DBConfig{
DB: config.DB,
}
var plak Plak
key := r.PathValue("key")
if dbConf.UrlExist(key) {
plak = Plak{
Key: key,
DB: config.DB,
}
plak = plak.GetContent()
if r.PathValue("settings") == "raw" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
_, err := io.WriteString(w, plak.Content)
if err != nil {
log.Println(err)
}
} else {
t, err := template.ParseFS(config.Templates, "templates/paste.html")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
}
err = t.Execute(w, plak)
if err != nil {
log.Println(err)
}
}
} else {
w.WriteHeader(http.StatusNotFound)
}
}
// Delete manage plak deletion endpoint
func (config WebConfig) Delete(w http.ResponseWriter, r *http.Request) {
dbConf := database.DBConfig{
DB: config.DB,
}
key := r.PathValue("key")
if dbConf.UrlExist(key) {
secret := r.URL.Query().Get("secret")
if dbConf.VerifySecret(key, secret) {
plak := Plak{
Key: key,
DB: config.DB,
}
err := plak.deletePlak()
if err != nil {
log.Println(err)
}
w.WriteHeader(http.StatusNoContent)
return
} else {
w.WriteHeader(http.StatusForbidden)
return
}
}
w.WriteHeader(http.StatusNotFound)
}
// deletePlak Delete plak from database
func (plak Plak) deletePlak() error {
err := plak.DB.Del(ctx, plak.Key).Err()
if err != nil {
log.Println(err)
return &DeletePlakError{Name: plak.Key, Err: err}
}
return nil
}
// GetContent get plak content
func (plak Plak) GetContent() Plak {
plak.Content = plak.DB.HGet(ctx, plak.Key, "content").Val()
return plak
}