2023-06-07 20:51:54 +03:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2023-06-17 21:36:15 +03:00
|
|
|
"fmt"
|
|
|
|
"github.com/lus/pasty/internal/maps"
|
2023-06-07 20:51:54 +03:00
|
|
|
"github.com/lus/pasty/internal/pastes"
|
|
|
|
"github.com/lus/pasty/internal/randx"
|
2023-06-17 21:36:15 +03:00
|
|
|
"github.com/lus/pasty/internal/static"
|
2023-06-07 20:51:54 +03:00
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type v2EndpointCreatePastePayload struct {
|
|
|
|
Content string `json:"content"`
|
|
|
|
Metadata map[string]any `json:"metadata"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (server *Server) v2EndpointCreatePaste(writer http.ResponseWriter, request *http.Request) {
|
|
|
|
// Read, parse and validate the request payload
|
|
|
|
body, err := io.ReadAll(request.Body)
|
|
|
|
if err != nil {
|
2023-06-17 18:00:44 +03:00
|
|
|
writeErr(request, writer, err)
|
2023-06-07 20:51:54 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
payload := new(v2EndpointCreatePastePayload)
|
|
|
|
if err := json.Unmarshal(body, payload); err != nil {
|
2023-06-17 18:00:44 +03:00
|
|
|
writeErr(request, writer, err)
|
2023-06-07 20:51:54 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
if payload.Content == "" {
|
|
|
|
writeString(writer, http.StatusBadRequest, "missing paste content")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if server.PasteLengthCap > 0 && len(payload.Content) > server.PasteLengthCap {
|
|
|
|
writeString(writer, http.StatusBadRequest, "too large paste content")
|
|
|
|
return
|
|
|
|
}
|
2023-06-17 21:36:15 +03:00
|
|
|
if payload.Metadata != nil && maps.ExceedsDimensions(payload.Metadata, static.MaxMetadataWidth, static.MaxMetadataDepth) {
|
|
|
|
writeString(writer, http.StatusBadRequest, fmt.Sprintf("metadata exceeds maximum dimensions (max. width: %d; max. depth: %d)", static.MaxMetadataWidth, static.MaxMetadataDepth))
|
|
|
|
return
|
|
|
|
}
|
2023-06-07 20:51:54 +03:00
|
|
|
|
|
|
|
id, err := pastes.GenerateID(request.Context(), server.Storage.Pastes(), server.PasteIDCharset, server.PasteIDLength)
|
|
|
|
if err != nil {
|
2023-06-17 18:00:44 +03:00
|
|
|
writeErr(request, writer, err)
|
2023-06-07 20:51:54 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
paste := &pastes.Paste{
|
|
|
|
ID: id,
|
|
|
|
Content: payload.Content,
|
|
|
|
Created: time.Now().Unix(),
|
|
|
|
Metadata: payload.Metadata,
|
|
|
|
}
|
|
|
|
|
|
|
|
modificationToken := ""
|
|
|
|
if server.ModificationTokensEnabled {
|
|
|
|
modificationToken = randx.String(server.ModificationTokenCharset, server.ModificationTokenLength)
|
|
|
|
paste.ModificationToken = modificationToken
|
|
|
|
|
|
|
|
if err := paste.HashModificationToken(); err != nil {
|
2023-06-17 18:00:44 +03:00
|
|
|
writeErr(request, writer, err)
|
2023-06-07 20:51:54 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := server.Storage.Pastes().Upsert(request.Context(), paste); err != nil {
|
2023-06-17 18:00:44 +03:00
|
|
|
writeErr(request, writer, err)
|
2023-06-07 20:51:54 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cpy := *paste
|
|
|
|
cpy.ModificationToken = modificationToken
|
2023-06-17 18:00:44 +03:00
|
|
|
writeJSONOrErr(request, writer, http.StatusCreated, cpy)
|
2023-06-07 20:51:54 +03:00
|
|
|
}
|