Implement paste metadata

This commit is contained in:
Lukas Schulte Pelkum 2021-07-19 15:11:52 +02:00
parent 08611f394e
commit 71477f71f6
No known key found for this signature in database
GPG Key ID: 408DA7CA81DB885C
7 changed files with 72 additions and 16 deletions

View File

@ -8,12 +8,13 @@ import (
// Paste represents a saved paste
type Paste struct {
ID string `json:"id" bson:"_id"`
Content string `json:"content" bson:"content"`
DeletionToken string `json:"deletionToken,omitempty" bson:"deletionToken"` // Required for legacy paste storage support
ModificationToken string `json:"modificationToken,omitempty" bson:"modificationToken"`
Created int64 `json:"created" bson:"created"`
AutoDelete bool `json:"autoDelete" bson:"autoDelete"`
ID string `json:"id" bson:"_id"`
Content string `json:"content" bson:"content"`
DeletionToken string `json:"deletionToken,omitempty" bson:"deletionToken"` // Required for legacy paste storage support
ModificationToken string `json:"modificationToken,omitempty" bson:"modificationToken"`
Created int64 `json:"created" bson:"created"`
AutoDelete bool `json:"autoDelete" bson:"autoDelete"`
Metadata map[string]interface{} `json:"metadata" bson:"metadata"`
}
// HashModificationToken hashes the current modification token of a paste

View File

@ -0,0 +1,5 @@
begin;
alter table if exists "pastes" drop column "metadata";
commit;

View File

@ -0,0 +1,5 @@
begin;
alter table if exists "pastes" add column "metadata" jsonb not null;
commit;

View File

@ -82,7 +82,7 @@ func (driver *PostgresDriver) Get(id string) (*shared.Paste, error) {
row := driver.pool.QueryRow(context.Background(), query, id)
paste := new(shared.Paste)
if err := row.Scan(&paste.ID, &paste.Content, &paste.ModificationToken, &paste.Created, &paste.AutoDelete); err != nil {
if err := row.Scan(&paste.ID, &paste.Content, &paste.ModificationToken, &paste.Created, &paste.AutoDelete, &paste.Metadata); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
@ -100,10 +100,11 @@ func (driver *PostgresDriver) Save(paste *shared.Paste) error {
SET content = excluded.token,
modificationToken = excluded.modificationToken,
created = excluded.created,
autoDelete = excluded.autoDelete
autoDelete = excluded.autoDelete,
metadata = excluded.metadata
`
_, err := driver.pool.Exec(context.Background(), query, paste.ID, paste.Content, paste.ModificationToken, paste.Created, paste.AutoDelete)
_, err := driver.pool.Exec(context.Background(), query, paste.ID, paste.Content, paste.ModificationToken, paste.Created, paste.AutoDelete, paste.Metadata)
return err
}

View File

@ -0,0 +1,26 @@
package v1
import "github.com/lus/pasty/internal/shared"
type legacyPaste struct {
ID string `json:"id"`
Content string `json:"content"`
DeletionToken string `json:"deletionToken,omitempty"`
Created int64 `json:"created"`
AutoDelete bool `json:"autoDelete"`
}
func legacyFromModern(paste *shared.Paste) *legacyPaste {
deletionToken := paste.ModificationToken
if deletionToken == "" {
deletionToken = paste.DeletionToken
}
return &legacyPaste{
ID: paste.ID,
Content: paste.Content,
DeletionToken: deletionToken,
Created: paste.Created,
AutoDelete: paste.AutoDelete,
}
}

View File

@ -37,11 +37,11 @@ func v1GetPaste(ctx *fasthttp.RequestCtx) {
ctx.SetBodyString("paste not found")
return
}
paste.DeletionToken = ""
paste.ModificationToken = ""
legacyPaste := legacyFromModern(paste)
legacyPaste.DeletionToken = ""
// Respond with the paste
jsonData, err := json.Marshal(paste)
jsonData, err := json.Marshal(legacyPaste)
if err != nil {
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
ctx.SetBodyString(err.Error())
@ -115,9 +115,8 @@ func v1PostPaste(ctx *fasthttp.RequestCtx) {
}
// Respond with the paste
pasteCopy := *paste
pasteCopy := legacyFromModern(paste)
pasteCopy.DeletionToken = modificationToken
pasteCopy.ModificationToken = ""
jsonData, err := json.Marshal(pasteCopy)
if err != nil {
ctx.SetStatusCode(fasthttp.StatusInternalServerError)

View File

@ -40,6 +40,10 @@ func middlewareInjectPaste(next fasthttp.RequestHandler) fasthttp.RequestHandler
return
}
if paste.Metadata == nil {
paste.Metadata = map[string]interface{}{}
}
ctx.SetUserValue("_paste", paste)
next(ctx)
@ -90,7 +94,8 @@ func endpointGetPaste(ctx *fasthttp.RequestCtx) {
}
type endpointCreatePastePayload struct {
Content string `json:"content"`
Content string `json:"content"`
Metadata map[string]interface{} `json:"metadata"`
}
// endpointCreatePaste handles the 'POST /v2/pastes' endpoint
@ -122,11 +127,15 @@ func endpointCreatePaste(ctx *fasthttp.RequestCtx) {
}
// Prepare the paste object
if payload.Metadata == nil {
payload.Metadata = map[string]interface{}{}
}
paste := &shared.Paste{
ID: id,
Content: payload.Content,
Created: time.Now().Unix(),
AutoDelete: config.Current.AutoDelete.Enabled,
Metadata: payload.Metadata,
}
// Create a new modification token if enabled
@ -165,7 +174,8 @@ func endpointCreatePaste(ctx *fasthttp.RequestCtx) {
}
type endpointModifyPastePayload struct {
Content *string `json:"content"`
Content *string `json:"content"`
Metadata map[string]interface{} `json:"metadata"`
}
// endpointModifyPaste handles the 'PATCH /v2/pastes/{id}' endpoint
@ -193,6 +203,15 @@ func endpointModifyPaste(ctx *fasthttp.RequestCtx) {
if payload.Content != nil {
paste.Content = *payload.Content
}
if payload.Metadata != nil {
for key, value := range payload.Metadata {
if value == nil {
delete(paste.Metadata, key)
continue
}
paste.Metadata[key] = value
}
}
// Save the modified paste
if err := storage.Current.Save(paste); err != nil {