Commit e5d5430

Eric Bower  ·  2026-08-11 13:56:36 -0400 EDT
parent 06944c5
refactor(pgs): validate pico+ before uploading so we don't create empty projects
3 files changed,  +28, -12
+1, -0
1@@ -194,6 +194,7 @@ services:
2     environment:
3       APP_DOMAIN: ${PGS_DOMAIN:-pgs.sh}
4       APP_EMAIL: ${PGS_EMAIL:-hello@pico.sh}
5+      DATABASE_URL: ${DATABASE_URL}
6     volumes:
7       - ${PGS_CADDYFILE}:/etc/caddy/Caddyfile
8       - ./data/pgs-caddy/data:/data
+24, -10
 1@@ -27,6 +27,7 @@ import (
 2 type ctxBucketKey struct{}
 3 type ctxStorageSizeKey struct{}
 4 type ctxProjectKey struct{}
 5+type ctxFeatureFlagKey struct{}
 6 type ctxDenylistKey struct{}
 7 
 8 type DenyList struct {
 9@@ -59,6 +60,19 @@ func setProject(s *pssh.SSHServerConnSession, project *db.Project) {
10 	s.SetValue(ctxProjectKey{}, project)
11 }
12 
13+func getFeatureFlag(s *pssh.SSHServerConnSession) *db.FeatureFlag {
14+	v := s.Context().Value(ctxFeatureFlagKey{})
15+	if v == nil {
16+		return nil
17+	}
18+	ff := s.Context().Value(ctxFeatureFlagKey{}).(*db.FeatureFlag)
19+	return ff
20+}
21+
22+func setFeatureFlag(s *pssh.SSHServerConnSession, ff *db.FeatureFlag) {
23+	s.SetValue(ctxFeatureFlagKey{}, ff)
24+}
25+
26 func getBucket(s *pssh.SSHServerConnSession) (storage.Bucket, error) {
27 	bucket := s.Context().Value(ctxBucketKey{}).(storage.Bucket)
28 	if bucket.Name == "" {
29@@ -205,19 +219,23 @@ func (h *UploadAssetHandler) Validate(s *pssh.SSHServerConnSession) error {
30 		return err
31 	}
32 
33+	ff, err := findPlusFF(h.Cfg.DB, h.Cfg, user.ID)
34+	if err != nil {
35+		return err
36+	}
37+	setFeatureFlag(s, ff)
38+
39 	assetBucket := shared.GetAssetBucketName(user.ID)
40 	bucket, err := h.Cfg.Storage.UpsertBucket(assetBucket)
41 	if err != nil {
42 		return err
43 	}
44-
45 	s.SetValue(ctxBucketKey{}, bucket)
46 
47 	totalStorageSize, err := h.Cfg.Storage.GetBucketQuota(bucket)
48 	if err != nil {
49 		return err
50 	}
51-
52 	s.SetValue(ctxStorageSizeKey{}, totalStorageSize)
53 
54 	logger.Info(
55@@ -337,14 +355,6 @@ func (h *UploadAssetHandler) Write(s *pssh.SSHServerConnSession, entry *sendutil
56 		return "", err
57 	}
58 
59-	featureFlag, err := findPlusFF(h.Cfg.DB, h.Cfg, user.ID)
60-	if err != nil {
61-		return "", err
62-	}
63-	if !featureFlag.IsValid() && pgsdb.IsProjectPrivate(projectName) {
64-		return "", fmt.Errorf("private projects are only allowed for pico+ users")
65-	}
66-
67 	// calculate the filsize difference between the same file already
68 	// stored and the updated file being uploaded
69 	assetFilename := shared.GetAssetFileName(entry)
70@@ -383,6 +393,10 @@ func (h *UploadAssetHandler) Write(s *pssh.SSHServerConnSession, entry *sendutil
71 		return "", err
72 	}
73 
74+	featureFlag := getFeatureFlag(s)
75+	if featureFlag == nil {
76+		return "", fmt.Errorf("pico+ feature flag ctx not set")
77+	}
78 	// SFTP does not report file size so the more performant way to
79 	//   check filesize constraints is to try and upload the file to s3
80 	//	 with a specialized reader that raises an error if the filesize limit
+3, -2
 1@@ -186,7 +186,6 @@ func (m *ServicesList) getServiceKv() []Kv {
 2 		{"prose", "active"},
 3 		{"pipe", "active"},
 4 		{"pastes", "active"},
 5-		{"rss-to-email", "active"},
 6 	}
 7 
 8 	if hasPlus {
 9@@ -195,13 +194,15 @@ func (m *ServicesList) getServiceKv() []Kv {
10 			[]string{"pages", "active"},
11 			[]string{"tuns", "active"},
12 			[]string{"irc bouncer", "active"},
13+			[]string{"rss-to-email", "active"},
14 		)
15 	} else {
16 		data = append(
17 			data,
18-			[]string{"pages", "free tier"},
19+			[]string{"pages", "pico+"},
20 			[]string{"tuns", "pico+"},
21 			[]string{"irc bouncer", "pico+"},
22+			[]string{"rss-to-email", "pico+"},
23 		)
24 	}
25