repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / apps / prose
Antonio Mika  ·  2025-03-12

scp_hooks.go

 1package prose
 2
 3import (
 4	"fmt"
 5	"strings"
 6
 7	"slices"
 8
 9	"github.com/picosh/pico/pkg/db"
10	"github.com/picosh/pico/pkg/filehandlers"
11	"github.com/picosh/pico/pkg/pssh"
12	"github.com/picosh/pico/pkg/shared"
13	"github.com/picosh/utils"
14	pipeUtil "github.com/picosh/utils/pipe"
15)
16
17type MarkdownHooks struct {
18	Cfg  *shared.ConfigSite
19	Db   db.DB
20	Pipe *pipeUtil.ReconnectReadWriteCloser
21}
22
23func (p *MarkdownHooks) FileValidate(s *pssh.SSHServerConnSession, data *filehandlers.PostMetaData) (bool, error) {
24	if !utils.IsTextFile(data.Text) {
25		err := fmt.Errorf(
26			"ERROR: (%s) invalid file must be plain text (utf-8), skipping",
27			data.Filename,
28		)
29		return false, err
30	}
31
32	// special styles css file we want to permit but no other css file.
33	// sometimes the directory is provided in the filename, so we want to
34	// remove that before we perform this check.
35	if strings.Replace(data.Filename, "/", "", 1) == "_styles.css" {
36		return true, nil
37	}
38
39	if !utils.IsExtAllowed(data.Filename, p.Cfg.AllowedExt) {
40		extStr := strings.Join(p.Cfg.AllowedExt, ",")
41		err := fmt.Errorf(
42			"ERROR: (%s) invalid file, format must be (%s), skipping",
43			data.Filename,
44			extStr,
45		)
46		return false, err
47	}
48
49	if data.FileSize > MAX_FILE_SIZE {
50		return false, fmt.Errorf(
51			"ERROR: file (%s) has exceeded maximum file size (%d bytes)",
52			data.Filename,
53			MAX_FILE_SIZE,
54		)
55	}
56
57	return true, nil
58}
59
60func (p *MarkdownHooks) FileMeta(s *pssh.SSHServerConnSession, data *filehandlers.PostMetaData) error {
61	parsedText, err := shared.ParseText(data.Text)
62	if err != nil {
63		return fmt.Errorf("%s: %w", data.Filename, err)
64	}
65
66	if parsedText.Title == "" {
67		data.Title = utils.ToUpper(data.Slug)
68	} else {
69		data.Title = parsedText.Title
70	}
71
72	data.Aliases = parsedText.Aliases
73	data.Tags = parsedText.Tags
74	data.Description = parsedText.Description
75
76	if parsedText.PublishAt != nil && !parsedText.PublishAt.IsZero() {
77		data.PublishAt = parsedText.MetaData.PublishAt
78	}
79
80	isHiddenFilename := slices.Contains(p.Cfg.HiddenPosts, data.Filename)
81	data.Hidden = parsedText.MetaData.Hidden || isHiddenFilename
82
83	return nil
84}