dashboard / git-pr / feat: range diff #16 rss

accepted · opened on 2024-08-19T21:12:53Z by erock
Help
# add changes to patch request
git format-patch main --stdout | ssh pr.pico.sh pr add 16
# add review to patch request
git format-patch main --stdout | ssh pr.pico.sh pr add --review 16
# remove patchset
ssh pr.pico.sh ps rm ps-x
# checkout all patches
ssh pr.pico.sh pr print 16 | git am -3
# print a diff between the last two patches in a patch request
ssh pr.pico.sh pr diff 16
# accept PR
ssh pr.pico.sh pr accept 16
# close PR
ssh pr.pico.sh pr close 16

Logs

erock created pr with ps-28 on 2024-08-18T15:28:14Z
erock added ps-29 on 2024-08-18T15:31:36Z
erock changed status on 2024-08-18T15:31:36Z {"status":"open"}
erock added ps-30 on 2024-08-18T16:05:53Z
erock changed status on 2024-08-18T16:05:53Z {"status":"open"}
erock changed pr name on 2024-08-18T16:06:30Z {"name":"feat: private obj store service"}
erock added ps-31 on 2024-08-18T16:39:07Z
erock changed status on 2024-08-18T16:39:07Z {"status":"open"}
erock added ps-32 on 2024-08-19T02:01:34Z
erock changed status on 2024-08-19T02:01:34Z {"status":"open"}
erock changed status on 2024-08-19T20:50:01Z {"status":"closed"}
erock changed status on 2024-11-06T15:04:22Z {"status":"accepted"}

Patchsets

ps-28 by erock on 2024-08-18T15:28:14Z
Range Diff ↕
1: 3bd44da ! 1: 9002592 chore(pgs): add validation to project names

@@ filehandlers/assets/handler.go
 
 	project := getProject(s)
 	projectName := shared.GetProjectName(entry)
+	err = shared.ValidateProjectName(projectName)
+	if err != nil {
+		return "", err
+	}
+
 	logger = logger.With("project", projectName)
 
 	// find, create, or update project if we haven't already done it

@@ pgs/cli.go
 func (c *Cmd) link(projectName, linkTo string) error {
 	c.Log.Info("user running `link` command", "user", c.User.Name, "project", projectName, "link", linkTo)
 
+	err := shared.ValidateProjectName(projectName)
+	if err != nil {
+		return err
+	}
+
 	projectDir := linkTo
-	_, err := c.Dbpool.FindProjectByName(c.User.ID, linkTo)
+	_, err = c.Dbpool.FindProjectByName(c.User.ID, linkTo)
 	if err != nil {
 		e := fmt.Errorf("(%s) project doesn't exist", linkTo)
 		return e

@@ shared/bucket.go
 	return fmt.Sprintf("static-%s", userID)
 }
 
+func ValidateProjectName(projectName string) error {
+	if projectName == "pico-private" {
+	if projectName == "pico-private" || projectName == "pico-imgs" {
+		return fmt.Errorf("%s is an invalid project name", projectName)
+	}
+	return nil
+}
+
 func GetProjectName(entry *utils.FileEntry) string {
 	if entry.Mode.IsDir() && strings.Count(entry.Filepath, string(os.PathSeparator)) == 0 {
 		return entry.Filepath
ps-29 by erock on 2024-08-18T15:31:36Z
Range Diff ↕
1: 9002592 = 1: 9002592 chore(pgs): add validation to project names
-: ------- > 2: cd17cf4 chore: update pobj
-: ------- > 3: a00def2 chore: complete impl
ps-30 by erock on 2024-08-18T16:05:53Z
Range Diff ↕
1: 9002592 = 1: 9002592 chore(pgs): add validation to project names
2: cd17cf4 = 2: cd17cf4 chore: update pobj
3: a00def2 = 3: a00def2 chore: complete impl
-: ------- > 4: 0ed7dc9 chore: update pobj
-: ------- > 5: 8ff1131 working!
ps-31 by erock on 2024-08-18T16:39:07Z
Range Diff ↕
1: 9002592 = 1: 9002592 chore(pgs): add validation to project names
2: cd17cf4 = 2: cd17cf4 chore: update pobj
3: a00def2 = 3: a00def2 chore: complete impl
4: 0ed7dc9 = 4: 0ed7dc9 chore: update pobj
5: 8ff1131 = 5: 8ff1131 working!
-: ------- > 6: 0c8ad0d chore(obj): prep service def
ps-32 by erock on 2024-08-19T02:01:34Z

Patchset ps-30

chore: update pobj

Eric Bower
2024-08-18T15:57:19Z
go.mod
+20 -1
go.sum
+40 -0
obj/config.go
+27 -0
obj/ssh.go
+99 -0

chore: complete impl

Eric Bower
2024-08-18T16:02:22Z
obj/ssh.go
+15 -13
Back to top

chore(pgs): add validation to project names

filehandlers/assets/handler.go link
+5 -0
 1diff --git a/filehandlers/assets/handler.go b/filehandlers/assets/handler.go
 2index 22edce6..1c32d82 100644
 3--- a/filehandlers/assets/handler.go
 4+++ b/filehandlers/assets/handler.go
 5@@ -268,6 +268,11 @@ func (h *UploadAssetHandler) Write(s ssh.Session, entry *utils.FileEntry) (strin
 6 
 7 	project := getProject(s)
 8 	projectName := shared.GetProjectName(entry)
 9+	err = shared.ValidateProjectName(projectName)
10+	if err != nil {
11+		return "", err
12+	}
13+
14 	logger = logger.With("project", projectName)
15 
16 	// find, create, or update project if we haven't already done it
pgs/cli.go link
+6 -1
 1diff --git a/pgs/cli.go b/pgs/cli.go
 2index 0af5802..8e82241 100644
 3--- a/pgs/cli.go
 4+++ b/pgs/cli.go
 5@@ -374,8 +374,13 @@ func (c *Cmd) unlink(projectName string) error {
 6 func (c *Cmd) link(projectName, linkTo string) error {
 7 	c.Log.Info("user running `link` command", "user", c.User.Name, "project", projectName, "link", linkTo)
 8 
 9+	err := shared.ValidateProjectName(projectName)
10+	if err != nil {
11+		return err
12+	}
13+
14 	projectDir := linkTo
15-	_, err := c.Dbpool.FindProjectByName(c.User.ID, linkTo)
16+	_, err = c.Dbpool.FindProjectByName(c.User.ID, linkTo)
17 	if err != nil {
18 		e := fmt.Errorf("(%s) project doesn't exist", linkTo)
19 		return e
shared/bucket.go link
+7 -0
 1diff --git a/shared/bucket.go b/shared/bucket.go
 2index 1257b55..e906cf0 100644
 3--- a/shared/bucket.go
 4+++ b/shared/bucket.go
 5@@ -17,6 +17,13 @@ func GetAssetBucketName(userID string) string {
 6 	return fmt.Sprintf("static-%s", userID)
 7 }
 8 
 9+func ValidateProjectName(projectName string) error {
10+	if projectName == "pico-private" || projectName == "pico-imgs" {
11+		return fmt.Errorf("%s is an invalid project name", projectName)
12+	}
13+	return nil
14+}
15+
16 func GetProjectName(entry *utils.FileEntry) string {
17 	if entry.Mode.IsDir() && strings.Count(entry.Filepath, string(os.PathSeparator)) == 0 {
18 		return entry.Filepath

chore: update pobj

go.mod link
+20 -1
 1diff --git a/go.mod b/go.mod
 2index 549e3ad..ace2286 100644
 3--- a/go.mod
 4+++ b/go.mod
 5@@ -32,7 +32,7 @@ require (
 6 	github.com/muesli/reflow v0.3.0
 7 	github.com/muesli/termenv v0.15.2
 8 	github.com/neurosnap/go-exif-remove v0.0.0-20221010134343-50d1e3c35577
 9-	github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a
10+	github.com/picosh/pobj v0.0.0-20240818155605-c7df7b892bf5
11 	github.com/picosh/send v0.0.0-20240709135413-81b1dd703a11
12 	github.com/picosh/tunkit v0.0.0-20240709033345-8315d4f3cd0e
13 	github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
14@@ -57,6 +57,25 @@ require (
15 	github.com/andybalholm/cascadia v1.3.2 // indirect
16 	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
17 	github.com/atotto/clipboard v0.1.4 // indirect
18+	github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect
19+	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect
20+	github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect
21+	github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect
22+	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect
23+	github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11 // indirect
24+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
25+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
26+	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
27+	github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 // indirect
28+	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
29+	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 // indirect
30+	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect
31+	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 // indirect
32+	github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0 // indirect
33+	github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect
34+	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect
35+	github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect
36+	github.com/aws/smithy-go v1.20.4 // indirect
37 	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
38 	github.com/aymerick/douceur v0.2.0 // indirect
39 	github.com/beorn7/perks v1.0.1 // indirect
go.sum link
+40 -0
 1diff --git a/go.sum b/go.sum
 2index 2577975..d87c73a 100644
 3--- a/go.sum
 4+++ b/go.sum
 5@@ -21,6 +21,44 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
 6 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
 7 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
 8 github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
 9+github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
10+github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
11+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 h1:70PVAiL15/aBMh5LThwgXdSQorVr91L127ttckI9QQU=
12+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4/go.mod h1:/MQxMqci8tlqDH+pjmoLu1i0tbWCUP1hhyMRuFxpQCw=
13+github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg=
14+github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs=
15+github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM=
16+github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c=
17+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE=
18+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI=
19+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11 h1:FEDZD/Axt5tKSkPAs967KZ++MkvYdBqr0a+cetRbjLM=
20+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11/go.mod h1:dvlsbA32KfvCzqwTiX7maABgFek2RyUuYEJ3kyn/PmQ=
21+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
22+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
23+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
24+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
25+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
26+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
27+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 h1:mimdLQkIX1zr8GIPY1ZtALdBQGxcASiBd2MOp8m/dMc=
28+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16/go.mod h1:YHk6owoSwrIsok+cAH9PENCOGoH5PU2EllX4vLtSrsY=
29+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI=
30+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc=
31+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 h1:GckUnpm4EJOAio1c8o25a+b3lVfwVzC9gnSBqiiNmZM=
32+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18/go.mod h1:Br6+bxfG33Dk3ynmkhsW2Z/t9D4+lRqdLDNCKi85w0U=
33+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ=
34+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c=
35+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 h1:jg16PhLPUiHIj8zYIW6bqzeQSuHVEiWnGA0Brz5Xv2I=
36+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16/go.mod h1:Uyk1zE1VVdsHSU7096h/rwnXDzOzYQVl+FNPhPw7ShY=
37+github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0 h1:Cso4Ev/XauMVsbwdhYEoxg8rxZWw43CFqqaPB5w3W2c=
38+github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0/go.mod h1:BSPI0EfnYUuNHPS0uqIo5VrRwzie+Fp+YhQOUs16sKI=
39+github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c=
40+github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM=
41+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI=
42+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac=
43+github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8=
44+github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0=
45+github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
46+github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
47 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
48 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
49 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
50@@ -224,6 +262,8 @@ github.com/picosh/go-rsync-receiver v0.0.0-20240709135253-1daf4b12a9fc h1:bvcsoO
51 github.com/picosh/go-rsync-receiver v0.0.0-20240709135253-1daf4b12a9fc/go.mod h1:i0iR3W4GSm1PuvVxB9OH32E5jP+CYkVb2NQSe0JCtlo=
52 github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a h1:Cr1xODiyd/SjjBRtYA9VX6Do3D+w+DansQzkb4NGeyA=
53 github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a/go.mod h1:VIkR1MZBvxSK2OO47jikxikAO/sKb/vTmXX5ZuYTIvo=
54+github.com/picosh/pobj v0.0.0-20240818155605-c7df7b892bf5 h1:gYoKG14iOjlYYCTiyFiOgybrqAOpnAqe6YU5QXnn8+A=
55+github.com/picosh/pobj v0.0.0-20240818155605-c7df7b892bf5/go.mod h1:tPv/ydMnuXlGVpWUMvBlcWlyn/xu9PsVPdncYibweWY=
56 github.com/picosh/send v0.0.0-20240709135413-81b1dd703a11 h1:ElTyYxJPPfAz+NLRL9qy+SQ9UYaSGlWXWl2yYrLPzCU=
57 github.com/picosh/send v0.0.0-20240709135413-81b1dd703a11/go.mod h1:RAgLDK3LrDK6pNeXtU9tjo28obl5DxShcTUk2nm/KCM=
58 github.com/picosh/senpai v0.0.0-20240503200611-af89e73973b0 h1:pBRIbiCj7K6rGELijb//dYhyCo8A3fvxW5dijrJVtjs=
obj/config.go link
+27 -0
 1diff --git a/obj/config.go b/obj/config.go
 2new file mode 100644
 3index 0000000..6e4747b
 4--- /dev/null
 5+++ b/obj/config.go
 6@@ -0,0 +1,27 @@
 7+package obj
 8+
 9+import (
10+	"github.com/picosh/pico/shared"
11+)
12+
13+func NewConfigSite() *shared.ConfigSite {
14+	debug := shared.GetEnv("OBJ_DEBUG", "0")
15+	storageDir := shared.GetEnv("OBJ_STORAGE_DIR", ".storage")
16+	minioURL := shared.GetEnv("MINIO_URL", "")
17+	minioUser := shared.GetEnv("MINIO_ROOT_USER", "")
18+	minioPass := shared.GetEnv("MINIO_ROOT_PASSWORD", "")
19+	dbURL := shared.GetEnv("DATABASE_URL", "")
20+
21+	cfg := shared.ConfigSite{
22+		Debug:      debug == "1",
23+		DbURL:      dbURL,
24+		StorageDir: storageDir,
25+		MinioURL:   minioURL,
26+		MinioUser:  minioUser,
27+		MinioPass:  minioPass,
28+		Space:      "obj",
29+		Logger:     shared.CreateLogger(debug == "1"),
30+	}
31+
32+	return &cfg
33+}
obj/ssh.go link
+99 -0
  1diff --git a/obj/ssh.go b/obj/ssh.go
  2new file mode 100644
  3index 0000000..ab70493
  4--- /dev/null
  5+++ b/obj/ssh.go
  6@@ -0,0 +1,99 @@
  7+package obj
  8+
  9+import (
 10+	"context"
 11+	"fmt"
 12+	"log/slog"
 13+	"os"
 14+	"os/signal"
 15+	"path/filepath"
 16+	"syscall"
 17+	"time"
 18+
 19+	"github.com/charmbracelet/wish"
 20+	"github.com/picosh/pico/db"
 21+	"github.com/picosh/pico/db/postgres"
 22+	"github.com/picosh/pico/filehandlers/util"
 23+	"github.com/picosh/pico/shared"
 24+	"github.com/picosh/pico/shared/storage"
 25+	"github.com/picosh/pobj"
 26+	"github.com/picosh/send/send/utils"
 27+)
 28+
 29+type AssetNamesPriv struct {
 30+	DBPool db.DB
 31+}
 32+
 33+var _ pobj.AssetNames = &AssetNamesPriv{}
 34+var _ pobj.AssetNames = (*AssetNamesPriv)(nil)
 35+
 36+func (an *AssetNamesPriv) BucketName(userName string) string {
 37+	user, _ := an.DBPool.FindUserForName(userName)
 38+	return shared.GetAssetBucketName(user.ID)
 39+}
 40+func (an *AssetNamesPriv) ObjectName(entry *utils.FileEntry) string {
 41+	return filepath.Join("pico-private", entry.Filepath)
 42+}
 43+
 44+func StartSshServer() {
 45+	logger := slog.Default()
 46+	host := pobj.GetEnv("OBJ_SSH_HOST", "0.0.0.0")
 47+	port := pobj.GetEnv("OBJ_SSH_PORT", "2222")
 48+	cfg := NewConfigSite()
 49+	dbpool := postgres.NewDB(cfg.DbURL, cfg.Logger)
 50+	defer dbpool.Close()
 51+
 52+	var st storage.StorageServe
 53+	var err error
 54+	if cfg.MinioURL == "" {
 55+		st, err = storage.NewStorageFS(cfg.StorageDir)
 56+	} else {
 57+		st, err = storage.NewStorageMinio(cfg.MinioURL, cfg.MinioUser, cfg.MinioPass)
 58+	}
 59+
 60+	assetNames := &AssetNamesPriv{
 61+		DBPool: dbpool,
 62+	}
 63+	objcfg := &pobj.Config{
 64+		Logger:     logger,
 65+		Storage:    st,
 66+		AssetNames: assetNames,
 67+	}
 68+
 69+	handler := pobj.NewUploadAssetHandler(objcfg)
 70+
 71+	sshAuth := util.NewSshAuthHandler(dbpool, logger, cfg)
 72+	s, err := wish.NewServer(
 73+		wish.WithAddress(fmt.Sprintf("%s:%s", host, port)),
 74+		wish.WithHostKeyPath("ssh_data/term_info_ed25519"),
 75+		wish.WithPublicKeyAuth(sshAuth.PubkeyAuthHandler),
 76+		pobj.WithProxy(handler),
 77+	)
 78+	if err != nil {
 79+		logger.Error(err.Error())
 80+		return
 81+	}
 82+
 83+	done := make(chan os.Signal, 1)
 84+	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
 85+	logger.Info(
 86+		"starting SSH server",
 87+		"host", host,
 88+		"port", port,
 89+	)
 90+	go func() {
 91+		if err = s.ListenAndServe(); err != nil {
 92+			logger.Error(err.Error())
 93+		}
 94+	}()
 95+
 96+	<-done
 97+	logger.Info("stopping SSH server")
 98+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 99+	defer func() {
100+		cancel()
101+	}()
102+	if err := s.Shutdown(ctx); err != nil {
103+		logger.Error(err.Error())
104+	}
105+}

chore: complete impl

cmd/obj/ssh/main.go link
+7 -0
 1diff --git a/cmd/obj/ssh/main.go b/cmd/obj/ssh/main.go
 2new file mode 100644
 3index 0000000..c2ee277
 4--- /dev/null
 5+++ b/cmd/obj/ssh/main.go
 6@@ -0,0 +1,7 @@
 7+package main
 8+
 9+import "github.com/picosh/pico/obj"
10+
11+func main() {
12+	obj.StartSshServer()
13+}
obj/ssh.go link
+15 -13
 1diff --git a/obj/ssh.go b/obj/ssh.go
 2index ab70493..0d4b0eb 100644
 3--- a/obj/ssh.go
 4+++ b/obj/ssh.go
 5@@ -10,8 +10,8 @@ import (
 6 	"syscall"
 7 	"time"
 8 
 9+	"github.com/charmbracelet/ssh"
10 	"github.com/charmbracelet/wish"
11-	"github.com/picosh/pico/db"
12 	"github.com/picosh/pico/db/postgres"
13 	"github.com/picosh/pico/filehandlers/util"
14 	"github.com/picosh/pico/shared"
15@@ -20,19 +20,20 @@ import (
16 	"github.com/picosh/send/send/utils"
17 )
18 
19-type AssetNamesPriv struct {
20-	DBPool db.DB
21-}
22+type AssetNamesPriv struct{}
23 
24 var _ pobj.AssetNames = &AssetNamesPriv{}
25 var _ pobj.AssetNames = (*AssetNamesPriv)(nil)
26 
27-func (an *AssetNamesPriv) BucketName(userName string) string {
28-	user, _ := an.DBPool.FindUserForName(userName)
29-	return shared.GetAssetBucketName(user.ID)
30+func (an *AssetNamesPriv) BucketName(sesh ssh.Session) (string, error) {
31+	user, err := util.GetUser(sesh.Context())
32+	if err != nil {
33+		return "", err
34+	}
35+	return shared.GetAssetBucketName(user.ID), nil
36 }
37-func (an *AssetNamesPriv) ObjectName(entry *utils.FileEntry) string {
38-	return filepath.Join("pico-private", entry.Filepath)
39+func (an *AssetNamesPriv) ObjectName(sesh ssh.Session, entry *utils.FileEntry) (string, error) {
40+	return filepath.Join("/pico-private", entry.Filepath), nil
41 }
42 
43 func StartSshServer() {
44@@ -50,10 +51,12 @@ func StartSshServer() {
45 	} else {
46 		st, err = storage.NewStorageMinio(cfg.MinioURL, cfg.MinioUser, cfg.MinioPass)
47 	}
48-
49-	assetNames := &AssetNamesPriv{
50-		DBPool: dbpool,
51+	if err != nil {
52+		logger.Error(err.Error())
53+		return
54 	}
55+
56+	assetNames := &AssetNamesPriv{}
57 	objcfg := &pobj.Config{
58 		Logger:     logger,
59 		Storage:    st,
60@@ -61,7 +64,6 @@ func StartSshServer() {
61 	}
62 
63 	handler := pobj.NewUploadAssetHandler(objcfg)
64-
65 	sshAuth := util.NewSshAuthHandler(dbpool, logger, cfg)
66 	s, err := wish.NewServer(
67 		wish.WithAddress(fmt.Sprintf("%s:%s", host, port)),