- commit
- 3a18c6d
- parent
- 4a34fa3
- author
- Eric Bower
- date
- 2023-08-13 20:33:59 +0000 UTC
feat: more pgs commands
3 files changed,
+172,
-7
M
db/db.go
+2,
-0
1@@ -210,7 +210,9 @@ type DB interface {
2 LinkToProject(userID, projectID, projectDir string) error
3 RemoveProject(projectID string) error
4 FindProjectByName(userID, name string) (*Project, error)
5+ FindProjectLinks(userID, name string) ([]*Project, error)
6 FindProjectsByUser(userID string) ([]*Project, error)
7+ FindProjectsByPrefix(userID, name string) ([]*Project, error)
8
9 Close() error
10 }
+63,
-5
1@@ -243,11 +243,13 @@ const (
2 sqlRemoveKeys = `DELETE FROM public_keys WHERE id = ANY($1::uuid[])`
3 sqlRemoveUsers = `DELETE FROM app_users WHERE id = ANY($1::uuid[])`
4
5- sqlInsertProject = `INSERT INTO projects (user_id, name, project_dir) VALUES ($1, $2, $3) RETURNING id;`
6- sqlFindProjectByName = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1 AND name = $2;`
7- sqlFindProjectsByUser = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1;`
8- sqlLinkToProject = `UPDATE projects SET project_dir = $1, updated_at = $2 WHERE id = $3;`
9- sqlRemoveProject = `DELETE FROM projects WHERE id = $1;`
10+ sqlInsertProject = `INSERT INTO projects (user_id, name, project_dir) VALUES ($1, $2, $3) RETURNING id;`
11+ sqlFindProjectByName = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1 AND name = $2;`
12+ sqlFindProjectsByUser = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1;`
13+ sqlFindProjectsByPrefix = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1 AND name = project_dir AND name ILIKE $2;`
14+ sqlFindProjectLinks = `SELECT id, user_id, name, project_dir FROM projects WHERE user_id = $1 AND name != project_dir AND project_dir = $2;`
15+ sqlLinkToProject = `UPDATE projects SET project_dir = $1, updated_at = $2 WHERE id = $3;`
16+ sqlRemoveProject = `DELETE FROM projects WHERE id = $1;`
17 )
18
19 type PsqlDB struct {
20@@ -1249,6 +1251,62 @@ func (me *PsqlDB) FindProjectByName(userID, name string) (*db.Project, error) {
21 return project, nil
22 }
23
24+func (me *PsqlDB) FindProjectLinks(userID, name string) ([]*db.Project, error) {
25+ var projects []*db.Project
26+ rs, err := me.Db.Query(sqlFindProjectLinks, userID, name)
27+ if err != nil {
28+ return nil, err
29+ }
30+ for rs.Next() {
31+ project := &db.Project{}
32+ err := rs.Scan(
33+ &project.ID,
34+ &project.UserID,
35+ &project.Name,
36+ &project.ProjectDir,
37+ )
38+ if err != nil {
39+ return nil, err
40+ }
41+
42+ projects = append(projects, project)
43+ }
44+
45+ if rs.Err() != nil {
46+ return nil, rs.Err()
47+ }
48+
49+ return projects, nil
50+}
51+
52+func (me *PsqlDB) FindProjectsByPrefix(userID, prefix string) ([]*db.Project, error) {
53+ var projects []*db.Project
54+ rs, err := me.Db.Query(sqlFindProjectsByPrefix, userID, prefix+"%")
55+ if err != nil {
56+ return nil, err
57+ }
58+ for rs.Next() {
59+ project := &db.Project{}
60+ err := rs.Scan(
61+ &project.ID,
62+ &project.UserID,
63+ &project.Name,
64+ &project.ProjectDir,
65+ )
66+ if err != nil {
67+ return nil, err
68+ }
69+
70+ projects = append(projects, project)
71+ }
72+
73+ if rs.Err() != nil {
74+ return nil, rs.Err()
75+ }
76+
77+ return projects, nil
78+}
79+
80 func (me *PsqlDB) FindProjectsByUser(userID string) ([]*db.Project, error) {
81 var projects []*db.Project
82 rs, err := me.Db.Query(sqlFindProjectsByUser, userID)
+107,
-2
1@@ -39,6 +39,8 @@ func getHelpText(userName, projectName string) string {
2 helpStr += fmt.Sprintf("`%s stats`: prints stats for user\n", sshCmdStr)
3 helpStr += fmt.Sprintf("`%s ls`: lists projects\n", sshCmdStr)
4 helpStr += fmt.Sprintf("`%s %s rm`: deletes `%s`\n", sshCmdStr, projectName, projectName)
5+ helpStr += fmt.Sprintf("`%s %s clean`: removes all projects that matches `%s` which is not linked\n", sshCmdStr, projectName, projectName)
6+ helpStr += fmt.Sprintf("`%s %s links`: lists all projects linked to `%s`\n", sshCmdStr, projectName, projectName)
7 helpStr += fmt.Sprintf("`%s %s link projectB`: symbolic link from `%s` to `projectB`\n", sshCmdStr, projectName, projectName)
8 helpStr += fmt.Sprintf("`%s %s unlink`: removes symbolic link for `%s`\n", sshCmdStr, projectName, projectName)
9 return helpStr
10@@ -183,7 +185,15 @@ func WishMiddleware(handler *uploadassets.UploadAssetHandler) wish.Middleware {
11 }
12 } else {
13 log.Infof("user (%s) has no project record (%s), creating ...", user.Name, projectName)
14- _, err := dbpool.InsertProject(user.ID, projectName, projectDir)
15+ id, err := dbpool.InsertProject(user.ID, projectName, projectName)
16+ if err != nil {
17+ log.Error(err)
18+ utils.ErrorHandler(session, err)
19+ return
20+ }
21+
22+ log.Infof("user (%s) linking (%s) to (%s) ...", user.Name, projectName, projectDir)
23+ err = dbpool.LinkToProject(user.ID, id, projectDir)
24 if err != nil {
25 log.Error(err)
26 utils.ErrorHandler(session, err)
27@@ -193,11 +203,106 @@ func WishMiddleware(handler *uploadassets.UploadAssetHandler) wish.Middleware {
28 out := fmt.Sprintf("(%s) now points to (%s)\n", projectName, linkTo)
29 _, _ = session.Write([]byte(out))
30 return
31+ } else if cmd == "links" {
32+ projects, err := dbpool.FindProjectLinks(user.ID, projectName)
33+ if err != nil {
34+ log.Error(err)
35+ utils.ErrorHandler(session, err)
36+ return
37+ }
38+
39+ if len(projects) == 0 {
40+ out := fmt.Sprintf("no projects linked to this project (%s) found\n", projectName)
41+ _, _ = session.Write([]byte(out))
42+ return
43+ }
44+
45+ for _, project := range projects {
46+ out := fmt.Sprintf("%s (links to: %s)\n", project.Name, project.ProjectDir)
47+ if project.Name == project.ProjectDir {
48+ out = fmt.Sprintf("%s\n", project.Name)
49+ }
50+ _, _ = session.Write([]byte(out))
51+ }
52+ } else if cmd == "clean" {
53+ log.Infof("user (%s) running `clean` command for (%s)", user.Name, projectName)
54+ if projectName == "" || projectName == "*" {
55+ e := fmt.Errorf("must provide valid prefix")
56+ log.Error(e)
57+ utils.ErrorHandler(session, e)
58+ return
59+ }
60+
61+ projects, err := dbpool.FindProjectsByPrefix(user.ID, projectName)
62+ if err != nil {
63+ log.Error(err)
64+ utils.ErrorHandler(session, err)
65+ }
66+
67+ bucketName := shared.GetAssetBucketName(user.ID)
68+ bucket, err := store.GetBucket(bucketName)
69+ if err != nil {
70+ log.Error(err)
71+ utils.ErrorHandler(session, err)
72+ return
73+ }
74+
75+ rmProjects := []*db.Project{}
76+ for _, project := range projects {
77+ links, err := dbpool.FindProjectLinks(user.ID, project.Name)
78+ if err != nil {
79+ log.Error(err)
80+ utils.ErrorHandler(session, err)
81+ }
82+
83+ if len(links) == 0 {
84+ out := fmt.Sprintf("project (%s) is available to delete", project.Name)
85+ _, _ = session.Write([]byte(out))
86+ rmProjects = append(rmProjects, project)
87+ }
88+ }
89+
90+ for _, project := range rmProjects {
91+ fileList, err := store.ListFiles(bucket, project.Name, true)
92+ if err != nil {
93+ log.Error(err)
94+ return
95+ }
96+
97+ for _, file := range fileList {
98+ err = store.DeleteFile(bucket, file.Name())
99+ if err == nil {
100+ // _, _ = session.Write([]byte(fmt.Sprintf("deleted (%s)\n", file.Name())))
101+ } else {
102+ log.Error(err)
103+ utils.ErrorHandler(session, err)
104+ }
105+ }
106+
107+ err = dbpool.RemoveProject(project.ID)
108+ if err != nil {
109+ log.Error(err)
110+ utils.ErrorHandler(session, err)
111+ }
112+ }
113 } else if cmd == "rm" {
114 log.Infof("user (%s) running `rm` command for (%s)", user.Name, projectName)
115 project, err := dbpool.FindProjectByName(user.ID, projectName)
116 if err == nil {
117- log.Infof("found project (%s) (%s), removing ...", projectName, project.ID)
118+ log.Infof("found project (%s) (%s), checking dependencies ...", projectName, project.ID)
119+
120+ links, err := dbpool.FindProjectLinks(user.ID, projectName)
121+ if err != nil {
122+ log.Error(err)
123+ utils.ErrorHandler(session, err)
124+ }
125+
126+ if len(links) > 0 {
127+ e := fmt.Errorf("project (%s) has (%d) other projects linking to it, can't delete project until they have been unlinked or removed, aborting ...", projectName, len(links))
128+ log.Error(e)
129+ return
130+ }
131+
132 err = dbpool.RemoveProject(project.ID)
133 if err != nil {
134 log.Error(err)