repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
dcfb7ac
parent
fc16c4a
author
Eric Bower
date
2024-12-11 18:38:58 +0000 UTC
fix: address CVE-2024-45337

Reference: https://github.com/golang/go/issues/70779
12 files changed,  +71, -136
M go.mod
M go.sum
M filehandlers/imgs/handler.go
+4, -7
 1@@ -48,7 +48,7 @@ func NewUploadImgHandler(dbpool db.DB, cfg *shared.ConfigSite, storage storage.S
 2 }
 3 
 4 func (h *UploadImgHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.FileInfo, sendutils.ReaderAtCloser, error) {
 5-	user, err := shared.GetUser(s.Context())
 6+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
 7 	if err != nil {
 8 		return nil, nil, err
 9 	}
10@@ -88,7 +88,7 @@ func (h *UploadImgHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.F
11 
12 func (h *UploadImgHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (string, error) {
13 	logger := h.Cfg.Logger
14-	user, err := shared.GetUser(s.Context())
15+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
16 	if err != nil {
17 		logger.Error("could not get user from ctx", "err", err.Error())
18 		return "", err
19@@ -145,10 +145,7 @@ func (h *UploadImgHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (str
20 		logger.Info("unable to find image, continuing", "filename", nextPost.Filename, "err", err.Error())
21 	}
22 
23-	featureFlag, err := shared.GetFeatureFlag(s.Context())
24-	if err != nil {
25-		return "", err
26-	}
27+	featureFlag := shared.FindPlusFF(h.DBPool, h.Cfg, user.ID)
28 	metadata := PostMetaData{
29 		OrigText:    text,
30 		Post:        &nextPost,
31@@ -192,7 +189,7 @@ func (h *UploadImgHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (str
32 }
33 
34 func (h *UploadImgHandler) Delete(s ssh.Session, entry *sendutils.FileEntry) error {
35-	user, err := shared.GetUser(s.Context())
36+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
37 	if err != nil {
38 		return err
39 	}
M filehandlers/imgs/img.go
+1, -1
1@@ -80,7 +80,7 @@ func (h *UploadImgHandler) writeImg(s ssh.Session, data *PostMetaData) error {
2 	if !valid {
3 		return err
4 	}
5-	user, err := shared.GetUser(s.Context())
6+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
7 	if err != nil {
8 		return err
9 	}
M filehandlers/post_handler.go
+3, -3
 1@@ -47,7 +47,7 @@ func NewScpPostHandler(dbpool db.DB, cfg *shared.ConfigSite, hooks ScpFileHooks,
 2 }
 3 
 4 func (h *ScpUploadHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.FileInfo, sendutils.ReaderAtCloser, error) {
 5-	user, err := shared.GetUser(s.Context())
 6+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
 7 	if err != nil {
 8 		return nil, nil, err
 9 	}
10@@ -76,7 +76,7 @@ func (h *ScpUploadHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.F
11 
12 func (h *ScpUploadHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (string, error) {
13 	logger := h.Cfg.Logger
14-	user, err := shared.GetUser(s.Context())
15+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
16 	if err != nil {
17 		logger.Error("error getting user from ctx", "err", err.Error())
18 		return "", err
19@@ -263,7 +263,7 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (str
20 
21 func (h *ScpUploadHandler) Delete(s ssh.Session, entry *sendutils.FileEntry) error {
22 	logger := h.Cfg.Logger
23-	user, err := shared.GetUser(s.Context())
24+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
25 	if err != nil {
26 		logger.Error("could not get user from ctx", "err", err.Error())
27 		return err
M filehandlers/router_handler.go
+2, -2
 1@@ -82,7 +82,7 @@ func (r *FileHandlerRouter) Read(s ssh.Session, entry *utils.FileEntry) (os.File
 2 
 3 func BaseList(s ssh.Session, fpath string, isDir bool, recursive bool, spaces []string, dbpool db.DB) ([]os.FileInfo, error) {
 4 	var fileList []os.FileInfo
 5-	user, err := shared.GetUser(s.Context())
 6+	user, err := dbpool.FindUser(s.Permissions().Extensions["user_id"])
 7 	if err != nil {
 8 		return fileList, err
 9 	}
10@@ -153,7 +153,7 @@ func (r *FileHandlerRouter) GetLogger() *slog.Logger {
11 }
12 
13 func (r *FileHandlerRouter) Validate(s ssh.Session) error {
14-	user, err := shared.GetUser(s.Context())
15+	user, err := r.DBPool.FindUser(s.Permissions().Extensions["user_id"])
16 	if err != nil {
17 		return err
18 	}
M go.mod
+5, -5
 1@@ -53,7 +53,7 @@ require (
 2 	go.abhg.dev/goldmark/anchor v0.1.1
 3 	go.abhg.dev/goldmark/hashtag v0.3.1
 4 	go.abhg.dev/goldmark/toc v0.10.0
 5-	golang.org/x/crypto v0.29.0
 6+	golang.org/x/crypto v0.31.0
 7 	gopkg.in/yaml.v2 v2.4.0
 8 )
 9 
10@@ -179,10 +179,10 @@ require (
11 	github.com/yusufpapurcu/wmi v1.2.4 // indirect
12 	golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
13 	golang.org/x/net v0.31.0 // indirect
14-	golang.org/x/sync v0.9.0 // indirect
15-	golang.org/x/sys v0.27.0 // indirect
16-	golang.org/x/term v0.26.0 // indirect
17-	golang.org/x/text v0.20.0 // indirect
18+	golang.org/x/sync v0.10.0 // indirect
19+	golang.org/x/sys v0.28.0 // indirect
20+	golang.org/x/term v0.27.0 // indirect
21+	golang.org/x/text v0.21.0 // indirect
22 	golang.org/x/time v0.8.0 // indirect
23 	google.golang.org/protobuf v1.35.2 // indirect
24 	mvdan.cc/xurls/v2 v2.5.0 // indirect
M go.sum
+10, -10
 1@@ -391,8 +391,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
 2 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 3 golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
 4 golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
 5-golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
 6-golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
 7+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
 8+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 9 golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
10 golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
11 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
12@@ -417,8 +417,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
13 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
14 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
15 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
16-golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
17-golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
18+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
19+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
20 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
21 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
22 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
23@@ -438,8 +438,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
24 golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
25 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
26 golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
27-golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
28-golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
29+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
30+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
31 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
32 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
33 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
34@@ -447,16 +447,16 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
35 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
36 golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
37 golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
38-golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
39-golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
40+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
41+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
42 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
43 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
44 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
45 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
46 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
47 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
48-golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
49-golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
50+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
51+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
52 golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
53 golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
54 golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
M pgs/tunnel.go
+11, -29
 1@@ -7,7 +7,6 @@ import (
 2 	"github.com/charmbracelet/ssh"
 3 	"github.com/picosh/pico/db"
 4 	"github.com/picosh/pico/shared"
 5-	"github.com/picosh/utils"
 6 )
 7 
 8 type TunnelWebRouter struct {
 9@@ -39,16 +38,14 @@ func createHttpHandler(apiConfig *shared.ApiConfig) CtxHttpBridge {
10 			"impersonating", asUser,
11 		)
12 
13-		pubkey, err := shared.GetPublicKey(ctx)
14-		if err != nil {
15-			log.Error(err.Error(), "subdomain", subdomain)
16+		pubkey := ctx.Permissions().Extensions["pubkey"]
17+		if pubkey == "" {
18+			log.Error("pubkey not found in extensions", "subdomain", subdomain)
19 			return http.HandlerFunc(shared.UnauthorizedHandler)
20 		}
21 
22-		pubkeyStr := utils.KeyForKeyText(pubkey)
23-
24 		log = log.With(
25-			"pubkey", pubkeyStr,
26+			"pubkey", pubkey,
27 		)
28 
29 		props, err := shared.GetProjectFromSubdomain(subdomain)
30@@ -72,7 +69,7 @@ func createHttpHandler(apiConfig *shared.ApiConfig) CtxHttpBridge {
31 			return http.HandlerFunc(shared.UnauthorizedHandler)
32 		}
33 
34-		requester, _ := dbh.FindUserForKey("", pubkeyStr)
35+		requester, _ := dbh.FindUserForKey("", pubkey)
36 		if requester != nil {
37 			log = log.With(
38 				"requester", requester.Name,
39@@ -89,33 +86,18 @@ func createHttpHandler(apiConfig *shared.ApiConfig) CtxHttpBridge {
40 			requester, _ = dbh.FindUserForName(asUser)
41 		}
42 
43-		shared.SetUser(ctx, requester)
44-
45-		if !HasProjectAccess(project, owner, requester, pubkey) {
46+		ctx.Permissions().Extensions["user_id"] = requester.ID
47+		publicKey, err := ssh.ParsePublicKey([]byte(pubkey))
48+		if err != nil {
49+			return http.HandlerFunc(shared.UnauthorizedHandler)
50+		}
51+		if !HasProjectAccess(project, owner, requester, publicKey) {
52 			log.Error("no access")
53 			return http.HandlerFunc(shared.UnauthorizedHandler)
54 		}
55 
56 		log.Info("user has access to site")
57 
58-		/* routes := []shared.Route{
59-			// special API endpoint for tunnel users accessing site
60-			shared.NewCorsRoute("GET", "/api/current_user", func(w http.ResponseWriter, r *http.Request) {
61-				w.Header().Set("Content-Type", "application/json")
62-				user, err := shared.GetUser(ctx)
63-				if err != nil {
64-					logger.Error("could not find user", "err", err.Error())
65-					shared.JSONError(w, err.Error(), http.StatusNotFound)
66-					return
67-				}
68-				pico := shared.NewUserApi(user, pubkey)
69-				err = json.NewEncoder(w).Encode(pico)
70-				if err != nil {
71-					log.Error(err.Error())
72-				}
73-			}),
74-		} */
75-
76 		routes := NewWebRouter(
77 			apiConfig.Cfg,
78 			logger,
M pgs/uploader.go
+6, -10
 1@@ -121,7 +121,7 @@ func (h *UploadAssetHandler) GetLogger() *slog.Logger {
 2 }
 3 
 4 func (h *UploadAssetHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.FileInfo, sendutils.ReaderAtCloser, error) {
 5-	user, err := shared.GetUser(s.Context())
 6+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
 7 	if err != nil {
 8 		return nil, nil, err
 9 	}
10@@ -155,7 +155,7 @@ func (h *UploadAssetHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os
11 func (h *UploadAssetHandler) List(s ssh.Session, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {
12 	var fileList []os.FileInfo
13 
14-	user, err := shared.GetUser(s.Context())
15+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
16 	if err != nil {
17 		return fileList, err
18 	}
19@@ -197,7 +197,7 @@ func (h *UploadAssetHandler) List(s ssh.Session, fpath string, isDir bool, recur
20 }
21 
22 func (h *UploadAssetHandler) Validate(s ssh.Session) error {
23-	user, err := shared.GetUser(s.Context())
24+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
25 	if err != nil {
26 		return err
27 	}
28@@ -248,7 +248,7 @@ func (h *UploadAssetHandler) findDenylist(bucket sst.Bucket, project *db.Project
29 }
30 
31 func (h *UploadAssetHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (string, error) {
32-	user, err := shared.GetUser(s.Context())
33+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
34 	if user == nil || err != nil {
35 		h.Cfg.Logger.Error("user not found in ctx", "err", err.Error())
36 		return "", err
37@@ -314,11 +314,7 @@ func (h *UploadAssetHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (s
38 		return "", err
39 	}
40 
41-	featureFlag, err := shared.GetFeatureFlag(s.Context())
42-	if err != nil {
43-		return "", err
44-	}
45-
46+	featureFlag := shared.FindPlusFF(h.DBPool, h.Cfg, user.ID)
47 	// calculate the filsize difference between the same file already
48 	// stored and the updated file being uploaded
49 	assetFilename := shared.GetAssetFileName(entry)
50@@ -424,7 +420,7 @@ func isSpecialFile(entry *sendutils.FileEntry) bool {
51 }
52 
53 func (h *UploadAssetHandler) Delete(s ssh.Session, entry *sendutils.FileEntry) error {
54-	user, err := shared.GetUser(s.Context())
55+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
56 	if err != nil {
57 		h.Cfg.Logger.Error("user not found in ctx", "err", err.Error())
58 		return err
M pico/file_handler.go
+4, -4
 1@@ -56,7 +56,7 @@ func (h *UploadHandler) Delete(s ssh.Session, entry *sendutils.FileEntry) error
 2 }
 3 
 4 func (h *UploadHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.FileInfo, sendutils.ReaderAtCloser, error) {
 5-	user, err := shared.GetUser(s.Context())
 6+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
 7 	if err != nil {
 8 		return nil, nil, err
 9 	}
10@@ -80,7 +80,7 @@ func (h *UploadHandler) Read(s ssh.Session, entry *sendutils.FileEntry) (os.File
11 
12 func (h *UploadHandler) List(s ssh.Session, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {
13 	var fileList []os.FileInfo
14-	user, err := shared.GetUser(s.Context())
15+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
16 	if err != nil {
17 		return fileList, err
18 	}
19@@ -135,7 +135,7 @@ func (h *UploadHandler) Validate(s ssh.Session) error {
20 		return fmt.Errorf("must have username set")
21 	}
22 
23-	shared.SetUser(s.Context(), user)
24+	s.Permissions().Extensions["user_id"] = user.ID
25 	return nil
26 }
27 
28@@ -276,7 +276,7 @@ func (h *UploadHandler) ProcessAuthorizedKeys(text []byte, logger *slog.Logger,
29 
30 func (h *UploadHandler) Write(s ssh.Session, entry *sendutils.FileEntry) (string, error) {
31 	logger := h.Cfg.Logger
32-	user, err := shared.GetUser(s.Context())
33+	user, err := h.DBPool.FindUser(s.Permissions().Extensions["user_id"])
34 	if err != nil {
35 		logger.Error(err.Error())
36 		return "", err
M pico/ssh.go
+0, -1
1@@ -28,7 +28,6 @@ import (
2 )
3 
4 func authHandler(ctx ssh.Context, key ssh.PublicKey) bool {
5-	shared.SetPublicKey(ctx, key)
6 	return true
7 }
8 
M pipe/cli.go
+1, -1
1@@ -141,7 +141,7 @@ func WishMiddleware(handler *CliHandler) wish.Middleware {
2 			logger := handler.Logger
3 			ctx := sesh.Context()
4 
5-			user, err := shared.GetUser(ctx)
6+			user, err := handler.DBPool.FindUser(sesh.Permissions().Extensions["user_id"])
7 			if err != nil {
8 				logger.Info("user not found", "err", err)
9 			}
M shared/ssh.go
+24, -63
  1@@ -1,7 +1,6 @@
  2 package shared
  3 
  4 import (
  5-	"fmt"
  6 	"log/slog"
  7 
  8 	"github.com/charmbracelet/ssh"
  9@@ -9,47 +8,6 @@ import (
 10 	"github.com/picosh/utils"
 11 )
 12 
 13-type ctxUserKey struct{}
 14-type ctxFeatureFlagKey struct{}
 15-
 16-func GetUser(ctx ssh.Context) (*db.User, error) {
 17-	user, ok := ctx.Value(ctxUserKey{}).(*db.User)
 18-	if !ok {
 19-		return user, fmt.Errorf("user not set on `ssh.Context()` for connection")
 20-	}
 21-	return user, nil
 22-}
 23-
 24-func SetUser(ctx ssh.Context, user *db.User) {
 25-	ctx.SetValue(ctxUserKey{}, user)
 26-}
 27-
 28-func GetFeatureFlag(ctx ssh.Context) (*db.FeatureFlag, error) {
 29-	ff, ok := ctx.Value(ctxFeatureFlagKey{}).(*db.FeatureFlag)
 30-	if !ok || ff.Name == "" {
 31-		return ff, fmt.Errorf("feature flag not set on `ssh.Context()` for connection")
 32-	}
 33-	return ff, nil
 34-}
 35-
 36-func SetFeatureFlag(ctx ssh.Context, ff *db.FeatureFlag) {
 37-	ctx.SetValue(ctxFeatureFlagKey{}, ff)
 38-}
 39-
 40-type ctxPublicKey struct{}
 41-
 42-func GetPublicKey(ctx ssh.Context) (ssh.PublicKey, error) {
 43-	pk, ok := ctx.Value(ctxPublicKey{}).(ssh.PublicKey)
 44-	if !ok {
 45-		return nil, fmt.Errorf("public key not set on `ssh.Context()` for connection")
 46-	}
 47-	return pk, nil
 48-}
 49-
 50-func SetPublicKey(ctx ssh.Context, pk ssh.PublicKey) {
 51-	ctx.SetValue(ctxPublicKey{}, pk)
 52-}
 53-
 54 type SshAuthHandler struct {
 55 	DBPool db.DB
 56 	Logger *slog.Logger
 57@@ -64,11 +22,28 @@ func NewSshAuthHandler(dbpool db.DB, logger *slog.Logger, cfg *ConfigSite) *SshA
 58 	}
 59 }
 60 
 61-func (r *SshAuthHandler) PubkeyAuthHandler(ctx ssh.Context, key ssh.PublicKey) bool {
 62-	SetPublicKey(ctx, key)
 63+func FindPlusFF(dbpool db.DB, cfg *ConfigSite, userID string) *db.FeatureFlag {
 64+	ff, _ := dbpool.FindFeatureForUser(userID, "plus")
 65+	// we have free tiers so users might not have a feature flag
 66+	// in which case we set sane defaults
 67+	if ff == nil {
 68+		ff = db.NewFeatureFlag(
 69+			userID,
 70+			"plus",
 71+			cfg.MaxSize,
 72+			cfg.MaxAssetSize,
 73+			cfg.MaxSpecialFileSize,
 74+		)
 75+	}
 76+	// this is jank
 77+	ff.Data.StorageMax = ff.FindStorageMax(cfg.MaxSize)
 78+	ff.Data.FileMax = ff.FindFileMax(cfg.MaxAssetSize)
 79+	ff.Data.SpecialFileMax = ff.FindSpecialFileMax(cfg.MaxSpecialFileSize)
 80+	return ff
 81+}
 82 
 83+func (r *SshAuthHandler) PubkeyAuthHandler(ctx ssh.Context, key ssh.PublicKey) bool {
 84 	pubkey := utils.KeyForKeyText(key)
 85-
 86 	user, err := r.DBPool.FindUserForKey(ctx.User(), pubkey)
 87 	if err != nil {
 88 		r.Logger.Error(
 89@@ -84,24 +59,10 @@ func (r *SshAuthHandler) PubkeyAuthHandler(ctx ssh.Context, key ssh.PublicKey) b
 90 		return false
 91 	}
 92 
 93-	ff, _ := r.DBPool.FindFeatureForUser(user.ID, "plus")
 94-	// we have free tiers so users might not have a feature flag
 95-	// in which case we set sane defaults
 96-	if ff == nil {
 97-		ff = db.NewFeatureFlag(
 98-			user.ID,
 99-			"plus",
100-			r.Cfg.MaxSize,
101-			r.Cfg.MaxAssetSize,
102-			r.Cfg.MaxSpecialFileSize,
103-		)
104+	if ctx.Permissions().Extensions == nil {
105+		ctx.Permissions().Extensions = map[string]string{}
106 	}
107-	// this is jank
108-	ff.Data.StorageMax = ff.FindStorageMax(r.Cfg.MaxSize)
109-	ff.Data.FileMax = ff.FindFileMax(r.Cfg.MaxAssetSize)
110-	ff.Data.SpecialFileMax = ff.FindSpecialFileMax(r.Cfg.MaxSpecialFileSize)
111-
112-	SetUser(ctx, user)
113-	SetFeatureFlag(ctx, ff)
114+	ctx.Permissions().Extensions["user_id"] = user.ID
115+	ctx.Permissions().Extensions["pubkey"] = pubkey
116 	return true
117 }