onasty/internal/models/note.go(view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package models
import (
"errors"
"regexp"
"time"
"github.com/gofrs/uuid/v5"
)
// read and unread are not allowed because those slugs might and will be interpreted as api routes
var notAllowedSlugs = map[string]struct{}{
"read": {},
"unread": {},
}
var (
ErrNoteContentIsEmpty = errors.New("note: content is empty")
ErrNoteSlugIsAlreadyInUse = errors.New("note: slug is already in use")
ErrNoteSlugIsInvalid = errors.New("note: slug is invalid")
ErrNoteExpired = errors.New("note: expired")
ErrNoteNotFound = errors.New("note: not found")
)
type Note struct {
ID uuid.UUID
Content string
Slug string
Password string
BurnBeforeExpiration bool
ReadAt time.Time
CreatedAt time.Time
ExpiresAt time.Time
}
var slugPattern = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
func (n Note) Validate() error {
if n.Content == "" {
return ErrNoteContentIsEmpty
}
if !slugPattern.MatchString(n.Slug) {
return ErrNoteSlugIsInvalid
}
if n.IsExpired() {
return ErrNoteExpired
}
if _, exists := notAllowedSlugs[n.Slug]; exists {
return ErrNoteSlugIsAlreadyInUse
}
return nil
}
func (n Note) IsExpired() bool {
return !n.ExpiresAt.IsZero() &&
n.ExpiresAt.Before(time.Now())
}
func (n Note) ShouldBeBurnt() bool {
return !n.ExpiresAt.IsZero() &&
n.BurnBeforeExpiration
}
func (n Note) IsRead() bool {
return !n.ReadAt.IsZero()
}
|