all repos

onasty @ 73fe76e

a one-time notes service

onasty/internal/models/note.go (view raw)

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