repos / pico

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

commit
88fbdfe
parent
8f012f8
author
Eric Bower
date
2025-04-04 12:17:17 -0400 EDT
fix(pgs): ability to create multiple projects in single ssh session

Previously we were caching the project when a user uploaded a bunch of
files.  This was an optimization that didn't account for when a user has
an active sftp connection where they create multiple projects in a
single session.  This code change performs an extra check to ensure we
are always creating new projects when necessary.
3 files changed,  +75, -2
M pkg/apps/pgs/db/memory.go
+8, -1
 1@@ -170,7 +170,14 @@ func (me *MemoryDB) FindProjectsByPrefix(userID, prefix string) ([]*db.Project,
 2 }
 3 
 4 func (me *MemoryDB) FindProjectsByUser(userID string) ([]*db.Project, error) {
 5-	return []*db.Project{}, errNotImpl
 6+	pjs := []*db.Project{}
 7+	for _, project := range me.Projects {
 8+		if project.UserID != userID {
 9+			continue
10+		}
11+		pjs = append(pjs, project)
12+	}
13+	return pjs, nil
14 }
15 
16 func (me *MemoryDB) FindProjects(userID string) ([]*db.Project, error) {
M pkg/apps/pgs/ssh_test.go
+63, -0
 1@@ -67,6 +67,28 @@ func TestSshServerSftp(t *testing.T) {
 2 		return
 3 	}
 4 
 5+	_, err = WriteFilesMultProjectsWithSftp(cfg, client)
 6+	if err != nil {
 7+		t.Error(err)
 8+		return
 9+	}
10+
11+	projects, err := dbpool.FindProjectsByUser(dbpool.Users[0].ID)
12+	if err != nil {
13+		t.Error(err)
14+		return
15+	}
16+
17+	names := ""
18+	for _, proj := range projects {
19+		names += "_" + proj.Name
20+	}
21+
22+	if names != "_test_mult_mult2" {
23+		t.Errorf("not all projects created: %s", names)
24+		return
25+	}
26+
27 	close(done)
28 
29 	p, err := os.FindProcess(os.Getpid())
30@@ -420,3 +442,44 @@ func WriteFileWithSftp(cfg *PgsConfig, conn *ssh.Client) (*os.FileInfo, error) {
31 
32 	return &fi, nil
33 }
34+
35+func WriteFilesMultProjectsWithSftp(cfg *PgsConfig, conn *ssh.Client) (*os.FileInfo, error) {
36+	// open an SFTP session over an existing ssh connection.
37+	client, err := sftp.NewClient(conn)
38+	if err != nil {
39+		cfg.Logger.Error("could not create sftp client", "err", err)
40+		return nil, err
41+	}
42+	defer client.Close()
43+
44+	f, err := client.Create("mult/hello.txt")
45+	if err != nil {
46+		cfg.Logger.Error("could not create file", "err", err)
47+		return nil, err
48+	}
49+	if _, err := f.Write([]byte("Hello world!")); err != nil {
50+		cfg.Logger.Error("could not write to file", "err", err)
51+		return nil, err
52+	}
53+
54+	f, err = client.Create("mult2/hello.txt")
55+	if err != nil {
56+		cfg.Logger.Error("could not create file", "err", err)
57+		return nil, err
58+	}
59+	if _, err := f.Write([]byte("Hello world!")); err != nil {
60+		cfg.Logger.Error("could not write to file", "err", err)
61+		return nil, err
62+	}
63+
64+	cfg.Logger.Info("closing", "err", f.Close())
65+
66+	// check it's there
67+	fi, err := client.Lstat("test/hello.txt")
68+	if err != nil {
69+		cfg.Logger.Error("could not get stat for file", "err", err)
70+		return nil, err
71+	}
72+
73+	return &fi, nil
74+}
M pkg/apps/pgs/uploader.go
+4, -1
 1@@ -307,7 +307,10 @@ func (h *UploadAssetHandler) Write(s *pssh.SSHServerConnSession, entry *sendutil
 2 	logger = logger.With("project", projectName)
 3 
 4 	// find, create, or update project if we haven't already done it
 5-	if project == nil {
 6+	// we need to also check if the project stored in ctx is the same project
 7+	// being uploaded since users can keep an ssh connection alive via sftp
 8+	// and created many projects in a single session
 9+	if project == nil || project.Name != projectName {
10 		project, err = h.Cfg.DB.UpsertProject(user.ID, projectName, projectName)
11 		if err != nil {
12 			logger.Error("upsert project", "err", err.Error())