78 lines
3.0 KiB
Go
78 lines
3.0 KiB
Go
package storage
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"gardomatic.kleiax.de/internal/platform/validate"
|
|
)
|
|
|
|
// MaxJournalAttachmentSize is the largest journal attachment accepted, in bytes.
|
|
const MaxJournalAttachmentSize = 25 << 20
|
|
|
|
// JournalModelInterface persists journal entries and their attachments.
|
|
type JournalModelInterface interface {
|
|
Insert(entry JournalEntry) (JournalEntry, error)
|
|
Get(gardenID, id int) (JournalEntry, error)
|
|
GetAllForGarden(gardenID int, entryType JournalEntryType) ([]JournalEntry, error)
|
|
Update(gardenID int, entry JournalEntry) (JournalEntry, error)
|
|
Delete(gardenID, id int) error
|
|
InsertAttachment(gardenID, entryID int, attachment JournalAttachment) (JournalAttachment, error)
|
|
GetAttachment(gardenID, entryID, attachmentID int) (JournalAttachment, error)
|
|
DeleteAttachment(gardenID, entryID, attachmentID int) error
|
|
}
|
|
|
|
// JournalEntryType distinguishes chronological journal entries from pinboard
|
|
// notes while sharing the same persistence model.
|
|
type JournalEntryType string
|
|
|
|
// Supported journal entry types.
|
|
const (
|
|
JournalEntryTypeJournal JournalEntryType = "journal"
|
|
JournalEntryTypePinboard JournalEntryType = "pinboard"
|
|
)
|
|
|
|
// JournalEntry is a garden note with optional tags and attachments.
|
|
type JournalEntry struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
AuthorID int `json:"author_id"`
|
|
AuthorName string `json:"author_name"`
|
|
AuthorColor string `json:"author_color"`
|
|
EntryType JournalEntryType `json:"entry_type"`
|
|
Title string `json:"title"`
|
|
Body string `json:"body"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
Attachments []JournalAttachment `json:"attachments,omitempty"`
|
|
}
|
|
|
|
// JournalAttachment contains either inline binary data or a reference to a
|
|
// reusable image-library item.
|
|
type JournalAttachment struct {
|
|
ID int `json:"id"`
|
|
EntryID int `json:"entry_id"`
|
|
FileName string `json:"file_name"`
|
|
MediaType string `json:"media_type"`
|
|
Size int64 `json:"size"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
Data []byte `json:"-"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
}
|
|
|
|
// ValidateJournalEntry applies the journal-entry input rules.
|
|
func ValidateJournalEntry(v *validate.Validator, entry JournalEntry) {
|
|
entryType := entry.EntryType
|
|
if entryType == "" {
|
|
entryType = JournalEntryTypeJournal
|
|
}
|
|
v.Check(validate.PermittedValue(entryType, JournalEntryTypeJournal, JournalEntryTypePinboard), "entry_type", "must be journal or pinboard")
|
|
if entryType == JournalEntryTypeJournal {
|
|
v.Check(strings.TrimSpace(entry.Title) != "", "title", "must be provided")
|
|
}
|
|
v.Check(len(entry.Title) <= 500, "title", "must not be more than 500 bytes long")
|
|
v.Check(len(entry.Body) <= 100_000, "body", "must not be more than 100000 bytes long")
|
|
}
|